c# - 如何从 C# 取消 C++/CX 中的异步操作

标签 c# windows-runtime async-await c++-cx cancellationtokensource

我正在尝试从 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 调用任务时,将 token 传递到 AsTask 扩展方法中不会执行任何操作。在调试 C++ 端时,ct 和 is_task_cancellation_requested() 函数均指示尚未请求取消。

最佳答案

试试这个。在您的 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 应用商店应用程序中创建两个按钮:

<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

关于c# - 如何从 C# 取消 C++/CX 中的异步操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21610005/

相关文章:

c# - 开发人员是否可以通过 "force"系统来防止 "Metro"应用程序在后台异步进程运行时被挂起?

javascript - eslint Warning Unexpected unnamed async function ,无论如何要摆脱它?

c# - await Task.Delay 花费的时间比预期的要长

c# - System.Net.Http.HttpClient.PostAsync 阻塞并且永不返回

c++ - Metro Windows 8 C++ 应用程序可以包含内联汇编器吗?

c# - Windows 8 原生自定义控件

c# - 比较图像和标记差异 c#

c# - Microsoft Dynamics CRM 工作流教程不起作用

c# - 如何改进 C# 中 get 调用方法的代码

visual-studio-2012 - Windows Store 应用程序的 TFSBuild 失败,错误为 APPX0105 : Cannot import the key file