HOW TO:指定特定排程器原則
排程器原則可讓您控制排程器在管理工作時所使用的策略。本主題將示範如何使用排程器原則來提高將進度列指示器列印至主控台之工作的執行緒優先順序。
如需使用自訂排程器原則搭配非同步代理程式的範例,請參閱 HOW TO:建立使用特定排程器原則的代理程式。
範例
下列範例會以平行方式執行兩項工作。第一項工作會計算第 n 個 Fibonacci 數字。第二項工作會將進度列指示器列印至主控台。
第一項工作會使用遞迴分解來計算 Fibonacci 數字。也就是說,每項工作都會以遞迴方式建立子工作來計算整體結果。使用遞迴分解的工作可能會使用所有可用的資源,因而影響其他工作。在這個範例中,列印進度列指示器的工作可能不會及時收到運算資源的存取權。
為了將運算資源的一般存取權提供給列印進度訊息的工作,這個範例會使用 HOW TO:管理排程器執行個體中所描述的步驟來建立具有自訂原則的排程器執行個體。這個自訂原則會指定讓這個執行緒具有最高等級的優先順序。
這個範例會使用 concurrency::call 和 concurrency::timer 列印進度列指示器的類別。這些類別都有使用參考其建構函式版本 concurrency::Scheduler 安排它們的物件。此範例會使用預設排程器來排程計算 Fibonacci 數字的工作,並且使用排程器執行個體來排程列印進度列指示器的工作。
為了說明使用具有自訂原則之排程器的優點,這個範例會執行整個工作兩次。這個範例會先使用預設排程器來排程兩項工作。這個範例接著會使用預設排程器來排程第一項工作,並且使用具有自訂原則的排程器來排程第二項工作。
// scheduler-policy.cpp
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <agents.h>
#include <iostream>
using namespace concurrency;
using namespace std;
// Computes the nth Fibonacci number.
// This function illustrates a lengthy operation and is therefore
// not optimized for performance.
int fibonacci(int n)
{
if (n < 2)
return n;
// Compute the components in parallel.
int n1, n2;
parallel_invoke(
[n,&n1] { n1 = fibonacci(n-1); },
[n,&n2] { n2 = fibonacci(n-2); }
);
return n1 + n2;
}
// Prints a progress indicator while computing the nth Fibonacci number.
void fibonacci_with_progress(Scheduler& progress_scheduler, int n)
{
// Use a task group to compute the Fibonacci number.
// The tasks in this group are scheduled by the current scheduler.
structured_task_group tasks;
auto task = make_task([n] {
fibonacci(n);
});
tasks.run(task);
// Create a call object that prints its input to the console.
// This example uses the provided scheduler to schedule the
// task that the call object performs.
call<wchar_t> c(progress_scheduler, [](wchar_t c) {
wcout << c;
});
// Connect the call object to a timer object. The timer object
// sends a progress message to the call object every 100 ms.
// This example also uses the provided scheduler to schedule the
// task that the timer object performs.
timer<wchar_t> t(progress_scheduler, 100, L'.', &c, true);
t.start();
// Wait for the task that computes the Fibonacci number to finish.
tasks.wait();
// Stop the timer.
t.stop();
wcout << L"done" << endl;
}
int wmain()
{
// Calculate the 38th Fibonacci number.
const int n = 38;
// Use the default scheduler to schedule the progress indicator while
// the Fibonacci number is calculated in the background.
wcout << L"Default scheduler:" << endl;
fibonacci_with_progress(*CurrentScheduler::Get(), n);
// Now use a scheduler that has a custom policy for the progress indicator.
// The custom policy specifies the thread priority to the highest
// priority class.
SchedulerPolicy policy(1, ContextPriority, THREAD_PRIORITY_HIGHEST);
Scheduler* scheduler = Scheduler::Create(policy);
// Register to be notified when the scheduler shuts down.
HANDLE hShutdownEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
scheduler->RegisterShutdownEvent(hShutdownEvent);
wcout << L"Scheduler that has a custom policy:" << endl;
fibonacci_with_progress(*scheduler, n);
// Release the final reference to the scheduler. This causes the scheduler
// to shut down.
scheduler->Release();
// Wait for the scheduler to shut down and destroy itself.
WaitForSingleObject(hShutdownEvent, INFINITE);
// Close the event handle.
CloseHandle(hShutdownEvent);
}
這個範例產生下列輸出。
Default scheduler:
...........................................................................done
Scheduler that has a custom policy:
...........................................................................done
雖然兩組工作產生的結果相同,但是使用自訂原則的版本可讓列印進度列指示器的工作以較高的優先順序執行,以便加快其回應速度。
編譯程式碼
將範例程式碼複製並貼上它在 Visual Studio 專案中,或將它貼在檔名為排程器 policy.cpp ,然後執行下列命令,Visual Studio 的命令提示字元] 視窗中。
cl.exe /EHsc scheduler-policy.cpp