2

我正在尝试从 C# 取消以 C++/CX 编写的操作。尽管我编写了两段代码,但在从 C# 端等待它时,我无法正确取消操作。这是一个例子:

从 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;
        });
    }

问题似乎是在跨 ABI 调用任务时,将令牌传递到 AsTask 扩展方法中没有任何作用。在调试 C++ 端时, ct 和 is_task_cancellation_requested() 函数都表明尚未请求取消。

4

1 回答 1

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 App 中创建两个按钮:

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

在Do按钮中调用组件的异步方法。

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.

于 2014-02-07T08:25:54.383 回答