ContinueWith 是否保证执行?

Is ContinueWith guaranteed to execute?

我有一些代码用作轻量级、非阻塞的关键部分。我希望无论 Task.Run 子句中的 _funccancellationToken 发生什么情况,都能保证 运行 的延续,使得 Exit 中的语句它的 finally 块将始终执行。

是否可以安全地假设下面的 finally 块,除了进程中的灾难性故障,将以与 finally normal operates with 大致相同的保证执行?

if (Enter())
{
    Task.Run<T>(_func, cancellationToken)
        .ContinueWith((antecedent) =>
        {
            try
            {
                antecedent.Wait(cancellationToken);
                Interlocked.Exchange<T>(ref _result, antecedent.Result);
            }
            catch (AggregateException e)
            {
                Interlocked.Exchange(ref _exceptions, e);
            }
            catch (OperationCanceledException)
            {
                ResetState();
            }
            catch (Exception e)
            {
                Interlocked.Exchange(ref _exceptions, new AggregateException(e));
            }
            finally
            {
                Exit();
            }
        })
}

基于MSDN documentation

The returned Task will not be scheduled for execution until the current task has completed, whether it completes due to running to completion successfully, faulting due to an unhandled exception, or exiting out early due to being canceled.

因此,除非 _func 永远不会 returns(例如,运行 处于无限循环中),否则延续将始终 运行。

并且当延续 运行s 时,finally 块保证按照 C# 规则执行。

所以答案是肯定的(当然 _func 永远不会 returns 除外)。

如果令牌在第一个任务 运行s 之前取消,continuation 将不会 运行,因此 finally 将不会执行。此处使用 VS 2015 进行测试:http://pastebin.com/9qmUYnqv

顺便说一句,编写的代码存在一些设计问题——让任务修改状态不是最好的主意;任务应该 return 值等等。在这种特殊情况下,对于非阻塞临界区,请考虑使用 SemaphoreSlim。