如何:指定特定的计划程序策略
利用计划程序策略,可以控制计划程序在管理任务时使用的策略。 本主题说明如何使用计划程序策略增加将进度指示器输出到控制台的任务的线程优先级别。
有关将自定义计划程序策略与异步代理一起使用的示例,请参见如何:创建使用特定计划程序策略的代理。
示例
下面的示例同时执行两个任务。 第一个任务将计算第 N 个斐波纳契数。 第二个任务将进度指示器输出到控制台。
第一个任务使用递归分解计算斐波纳契数。 也就是说,每个任务将以递归方式创建多个子任务以计算总体结果。 采用递归分解的任务可能会使用所有可用资源,从而使其他任务停止。 在此示例中,输出进度指示器的任务可能无法及时收到对计算资源的访问权。
为了向输出进度指示器的任务提供对计算资源的公平访问权,此示例使用如何:管理计划程序实例中所述步骤以创建具有自定义策略的计划程序实例。 自定义策略将线程优先级别指定为最高优先级别类。
此示例使用 Concurrency::call 和 Concurrency::timer 类输出进度指示器。 这两个类的构造函数版本可引用 Concurrency::Scheduler 对象,该对象可计划这些构造函数。 此示例使用默认计划程序来安排计算斐波纳契数的任务,并使用计划程序实例来安排输出进度指示器的任务。
为了说明使用具有自定义策略的计划程序的好处,此示例将整个任务执行两次。 此示例首先使用默认计划程序安排这两项任务, 然后使用默认计划程序安排第一个任务,并使用具有自定义策略的计划程序安排第二个任务。
// 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 项目中或一个名为 scheduler-policy.cpp 的文件中,然后在 Visual Studio 2010 命令提示符窗口中运行以下命令。
cl.exe /EHsc scheduler-policy.cpp