2

C++/CX で記述された操作を C# からキャンセルしようとしています。両方のコードを書いたにもかかわらず、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;
        });
    }

問題は、トークンを AsTask 拡張メソッドに渡すと、ABI を介してタスクを呼び出すときに何も行われないことです。C++ 側をデバッグすると、ct と is_task_cancellation_requested() 関数の両方がキャンセルが要求されていないことを示します。

4

1 に答える 1

2

これを試して。C++ Windows ランタイム コンポーネントで、たとえばスレッドを 2 秒間スリープさせるなど、時間がかかる処理を行います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 ストア アプリで 2 つのボタンを作成します。

<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し、2 秒以内にボタンをクリックしCancelます。を取得する必要がありSystem.Threading.OperationCanceledExceptionます。

于 2014-02-07T08:25:54.383 に答える