取消操作:
取消一个正在进行的task,方式大概分两种,一种是从内部取消,另外一种是从外部取消。
我们通过cancel_current_task 去从内部取消这个task
#include <ppltasks.h>
#include <iostream>
#include <array>
#include <list>
using
namespace Concurrency;
using
namespace std;
void do_work()
{
//
Simulate work.
wcout << L
"
Performing work...
" << endl;
wait(
250);
}
int _tmain(
int argc, _TCHAR* argv[])
{
wcout << L
"
Creating task...
" << endl;
task<
void> t([]() {
bool moreToDo =
true;
int i=
0;
while (moreToDo)
{
i++;
if(i==
4)
{
wcout<<L
"
In cancellation
"<<endl;
//
call this function to cancel
cancel_current_task();
}
do_work();
}
});
wait(
1000);
}
这里要说明一点的是,在我们声明这个task之后,我们并没有调用.wait() 或者.get() 去执行他。只是调用了wait(1000);这个task就被执行了。这个是因为,wait(1000)这个函数,表面上是让当前的线程休息1000毫秒,但是他会激发后台scheduled状态的task,当这个task声明之后,他的状态就是scheduled,当我们在主线程调用wait()的方法,之前声明的task就会被激发和执行,所以我们不需要调用.wait()或者.get()去执行他。
如果我们想从外部取消这个task,我们需要传一个token给这个task,然后我们通过 cancellation_token_source::cancel 这个方法去取消这个task
wcout << L"Creating task..." << endl;
cancellation_token_source cts;
auto token=cts.get_token();
task<
void> t([]() {
bool moreToDo =
true;
while (moreToDo)
{
//
Simulate work.
do_work();
}
},token);
wait(
1000);
cts.cancel();
//
Wait for the task to cancel.
wcout << L
"
Waiting for task to complete...
" << endl;
t.wait();
wcout << L
"
Done.
" << endl;
return
0;
在外部取消这个task的过程中,我们想在内部获得取消这个动作的信号。我们可以通过is_task_cancellation_requested 函数去获取
task<
void> t([]() {
bool moreToDo =
true;
while (moreToDo)
{
//
Check for cancellation.
if (is_task_cancellation_requested()) {
wcout << L
"
Get the cancel event
" << endl;
//
Cancel the current task.
cancel_current_task();
//
You must end this task in front line or in this line
moreToDo =
false;
}
else {
//
Perform work.
do_work();
}
}
}, token);
//
Wait for one second and then cancel the task.
wait(
1000);
wcout << L
"
Canceling task...
" << endl;
cts.cancel();
//
Wait for the task to cancel.
wcout << L
"
Waiting for task to complete...
" << endl;
t.wait();
这里要注意的是, 当我们调用cts.cancel()的时候,is_task_cancellation_requested 返回true,但是这个task并没有被取消,我们必须要在task里面手动调用cancel_current_task,或者通过其他办法让函数结束。如果我们不判断is_task_cancellation_requested 就不需要我们在task内部手动取消。
我们还可以注入callback 函数,在我们尝试外部取消的时候。
cancellation_token_source cts;
auto token=cts.get_token();
cancellation_token_registration cookie;
cookie=token.register_callback([](){ wcout << L
"
In cancellation callback...
" << endl;});
task<
void> t([]() {
bool moreToDo =
true;
while (moreToDo)
{
//
Simulate work.
do_work();
}
},token);
wait(
1000);
cts.cancel();
token.deregister_callback(cookie);
以上的例子都是基于while循环的,我认为这样可以便于理解。同样,我们也可以用event,在Concurrency namespace里面,系统事件已经被封装成event Class (Concurrency Runtime) 这个类,有set wait 等方法便于使用。下面的例子就是基于event 和callback函数的
//
task-cancellation-callback.cpp
//
compile with: /EHsc
#include <ppltasks.h>
#include <iostream>
using
namespace Concurrency;
using
namespace std;
int wmain()
{
cancellation_token_source cts;
auto token = cts.get_token();
//
An event that is set in the cancellation callback.
event e;
cancellation_token_registration cookie;
cookie = token.register_callback([&e, token, &cookie]() {
wcout << L
"
In cancellation callback...
" << endl;
e.
set();
//
Although not required, demonstrate how to unregister
//
the callback.
token.deregister_callback(cookie);
});
wcout << L
"
Creating task...
" << endl;
//
Create a task that waits to be canceled.
task<
void> t([&e]() {
e.wait();
}, token);
//
Cancel the task.
wcout << L
"
Canceling task...
" << endl;
cts.cancel();
//
Wait for the task to cancel.
t.wait();
wcout << L
"
Done.
" << endl;
}
这里还要注意deregister_callback,传入参数必须是引用类型。
最后关于取消操作,还要说一点就是如何给一个parallel_for 添加取消动作,首先,这个函数本是是没有支持取消操作的,我们要给他外面套一层task,通过取消外面的task,来取消里面的parallel_for。
int wmain()
{
cancellation_token_source cts;
//
//
Run a parallel_for loop in a call to run_with_cancellation_token.
wcout << L
"
Running a task with a cancellation token...
" << endl;
run_with_cancellation_token([cts] {
//
For illustration, cancel the overall operation on the third
//
iteration of a parallel loop. The parallel_for call implicitly
//
inherits the cancellation token of the parent task.
long counter =
0;
parallel_for(
0,
100, [cts, &counter](
int n) {
if (InterlockedIncrement(&counter) ==
3)
{
wstringstream ss;
ss << L
"
Canceling...
" << endl;
wcout << ss.str();
cts.cancel();
}
wstringstream ss;
ss << L
"
In iteration
" << n << L
"
of parallel_for...
" << endl;
wcout << ss.str();
});
}, cts.get_token());
wcout << L
"
Done.
" << endl;
}
引用自:http://msdn.microsoft.com/en-us/library/windows/apps/dd984117(v=vs.110).aspx