zoukankan      html  css  js  c++  java
  • C++异步编程 for VS2011(二)

    在上一篇文章中,我介绍一些在VS中C++异步编程的简单概念和语法。这篇,我们讨论一下异步编程中取消操作的概念。

    取消操作:

    取消一个正在进行的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(0100, [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

  • 相关阅读:
    例题6-8 Tree Uva548
    例题6-7 Trees on the level ,Uva122
    caffe Mac 安装
    Codeforces Round #467 (Div. 1) B. Sleepy Game
    Educational Codeforces Round37 E
    Educational Codeforces Round 36 (Rated for Div. 2) E. Physical Education Lessons
    Good Bye 2017 E. New Year and Entity Enumeration
    Good Bye 2017 D. New Year and Arbitrary Arrangement
    Codeforces Round #454 D. Seating of Students
    浙大紫金港两日游
  • 原文地址:https://www.cnblogs.com/zjjcy/p/2416700.html
Copyright © 2011-2022 走看看