1

我試圖取消從C#編寫的C++/CX中的操作。儘管我寫了兩段代碼,但在從C#端等待它時無法正確取消操作。這裏有一個例子:如何從C#中取消C++/CX中的異步操作

從C#:

var tcs = new CancellationTokenSource(); 
tcs.Cancel(); 
var class1 = new MyClass(); 
try 
{ 
    var asyncOp = await class1.DoSomeTaskAsync().AsTask(tcs.Token); 
} 
catch (OperationCanceledException oce) 
{ 
    //I want to get here 
    Handle(oce); 
} 

從C++:

IAsyncOperation<bool>^ MyClass::DoSomeTaskAsync(){ 
     return concurrency::create_async([](concurrency::cancellation_token ct) { 
      task<bool> my_task([]() { 
       doSomething1(); 
       if (concurrency::is_task_cancellation_requested()) 
       { 
        concurrency::cancel_current_task(); 
       } 
       doSomething2(); 
       return false; 
      }, ct); 
      return my_task; 
     }); 
    } 

的問題似乎是,通過令牌進入AsTask擴展方法跨越調用任務時不執行任何操作ABI。在調試C++端時,ct和is_task_cancellation_requested()函數都指示未請求取消。

+0

啓動異步操作後調用'txw.Cancel'。如果任務已被取消,請確保您的操作足以取消並多次詢問。 – kiewic

+0

我不知道爲什麼這是一個要求取消任務_after_它已經開始。如果您導航到頁面的情況如何,頁面會啓動一系列任務,然後啓動一些任務,然後您可以快速離開頁面。可能有一些任務尚未開始,您希望立即取消,對吧? – Kellen

+0

所以,你可以添加一個布爾值來表示你已經決定去別的地方,所以你不會開始任何其他的異步操作。我的**猜測**是,只有在調用「取消」之前生成的令牌將被取消。所以,如果你在調用'Cancel'之後啓動一個鏈接的異步操作,只要在調用'Cancel'之前生成了該標記,它就會被取消。 – kiewic

回答

2

試試這個。在您的C++ Windows運行時組件中,執行某些操作需要很長時間,例如,concurrency::wait(2000)會使線程休眠兩秒鐘(不要在真實應用程序中執行此操作)。

#include <ppltasks.h> 

using namespace Windows::Foundation; 

IAsyncOperation<bool>^ MyClass::DoSomeTaskAsync() 
{ 
    return concurrency::create_async([=](concurrency::cancellation_token token) 
    { 
     // Do something. 
     concurrency::wait(2000); 

     if (concurrency::is_task_cancellation_requested()) 
     { 
      concurrency::cancel_current_task(); 
     } 

     // Do something else. 
     concurrency::wait(2000); 

     return true; 
    }); 
} 

然後,在你的C#Windows Store應用創建兩個按鈕:

<Button x:Name="DoButton" Click="DoButton_Click">Do</Button> 
<Button x:Name="CancelButton" Click="CancelButton_Click">Cancel</Button> 

打電話給你的組件在異步方法做按鈕。

private System.Threading.CancellationTokenSource cts; 

private async void DoButton_Click(object sender, RoutedEventArgs e) 
{ 
    cts = new System.Threading.CancellationTokenSource(); 
    var class1 = new MyClass(); 
    try 
    { 
     var asyncOp = await class1.DoSomeTaskAsync().AsTask(cts.Token); 
     System.Diagnostics.Debug.WriteLine(asyncOp); 
    } 
    catch (OperationCanceledException oce) 
    { 
     // I want to get here. 
     System.Diagnostics.Debug.WriteLine(oce); 
    } 
} 

並取消在操作取消按鈕。

private void CancelButton_Click(object sender, RoutedEventArgs e) 
{ 
    cts.Cancel(); 
    cts = null; 
} 

運行的應用程序,請單擊Do按鈕兩秒鐘內點擊Cancel按鈕。你應該得到一個System.Threading.OperationCanceledException