簡體   English   中英

從CancellationToken.Register內部拋出C#拋出OperationCanceledException

[英]C# Throw OperationCanceledException from inside CancellationToken.Register

我有一個長時間運行的操作,想在5秒后取消。 不幸的是,不可能對IsCancellationRequested進行輪詢(長話短說)。

我使用下面的代碼在取消回調中引發了OperationCanceledException。 我想在主線程中捕獲異常並進行處理,以便可以完全退出應用程序。

這似乎無法正常工作,因為這會導致未處理的異常,並且應用程序無法正常終止。

任何幫助表示贊賞。 謝謝!

    void TestTimeOut()
    {
        var cts = new CancellationTokenSource();
        cts.CancelAfter(5000);

        try
        {
            var task = Task.Run(() => LongRunningOperation(cts.Token));
            task.ContinueWith(t => Console.WriteLine("Operation cancelled"), TaskContinuationOptions.OnlyOnFaulted);
            task.Wait();
        }
        catch (AggregateException e)
        {
            //Handle
        }
    }


    void LongRunningOperation(CancellationToken token)
    {
        CancellationTokenRegistration registration = token.Register(
            () =>
            {
                throw new OperationCanceledException(token); 
            });

        using (registration)
        {
            // long running operation here
        }
    }

您正在捕獲一個AggregateException但是實際上拋出了一個OperationCanceledException ,它將不會被捕獲。

進行更改以捕獲所有類型的異常,例如

catch (Exception ex) { ... }

解決。

您的代碼有很多No-No-es,但我想您只是將它用作問題演示。 解決方案是TaskCompletionSource ,我的演示也很丑陋,太多的Task.Run()層,如果使用Async,則應該一直異步。 因此,不要在PRD中使用它,自己研究TaskCompletionSource並找出更好的解決方案。

    static void LongRunningOperation(CancellationToken token)
    {
        TaskCompletionSource<int> tcs1 = new TaskCompletionSource<int>();
        token.Register(() => { tcs1.TrySetCanceled(token); });
        Task.Run(() =>
        {
            // long running operation here
            Thread.Sleep(10000);
            tcs1.TrySetResult(0);
        }, token);
        tcs1.Task.Wait();
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM