我正在.NET 4.0上的C#中工作,并已开始用BackgroundWorker替换许多嵌套的Task<T>设置。

“嵌套”具有以下形式:

var secondWorker = new BackgroundWorker();
secondWorker.DoWork += (sender, args) =>
{
    MoreThings();
};

var firstWorker = new BackgroundWorker();
firstWorker.DoWork += (sender, args) =>
{
    args.Result = this.Things();
};

firstWorker.RunWorkerCompleted += (sender, args) =>
{
    var result = (bool)args.Result;

    // possibly do things on UI

    if (result) { secondWorker.RunWorkerAsync(); }
};


secondWorker在这里扮演firstWorker的回调的角色。据我了解,使用Task<T>时的等效项是ContinueWith()的延续。但是,这不允许我决定是否在特定情况下根据控制流实际运行延续。

我认为这是非常不干净的-解决方法是:

var source = new CancellationTokenSource();
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

Task.Factory.StartNew(() => { return this.Things(); })
    .ContinueWith(t =>
        {
            // do things on UI

            if (!t.Result) { source.Cancel(); }
        }, CancellationToken.None, TaskContinuationOptions.NotOnFaulted, uiScheduler)
    .ContinueWith(t => { this.MoreThings(); }, source.Token);


这种工作方式,但是从我所看到的所有示例中,都以这种形式(从延续链中访问CancellationTokenSource-尽管未使用令牌的任务)看起来像是滥用了机制。这到底有多糟?根据其流程内部确定的信息,取消延续链的正确的“惯用”方法是什么?

(上面的代码具有预期的效果,但是我认为这是解决使用现有工具的任务的错误方法。我不是在批评我的“解决方案”,而是在寻求正确的解决方案这就是为什么我将其放在SO而不是Code Review上的原因。

最佳答案

通过继续,C#还提供了async方法功能。在此方案中,您的代码将如下所示:

async Task<bool> Things() { ... }
async Task MoreThings() { ... }

async Task RunStuff()
{
    if (await Things())
    {
        await MoreThings();
    }
}


具体细节取决于您的实施细节。这里重要的是,通过asyncawait,C#将自动生成一个状态机,该状态机将使所有乏味抽象出来,而无需处理连续性,从而使它们易于组织。

编辑:我想到您的实际Things()MoreThings()方法,您可能不想实际转换为async,因此您可以这样做:

async Task RunStuff()
{
    if (await Task.Run(() => Things()))
    {
        await Task.Run(() => MoreThings());
    }
}


这会将您的特定方法包装在异步任务中。

编辑2:有人向我指出,我在这里忽略了4.5之前的限制,以下应该起作用:

void RunStuff()
{
    Task.Factory.StartNew(() => Things()).ContinueWith(task =>
    {
        if (task.Result)
        {
            Task.Factory.StartNew(() => MoreThings());
        }
    });
}


反正就是这样。

关于c# - 从内部取消延续链,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26747792/

10-11 00:52