c# - 从内部取消延续链

标签 c# .net task-parallel-library continuations

我在 .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() 的延续;但是,这不允许我决定是否在特定情况下实际从控制流运行延续。

A - 根据我的理解非常不干净 - 解决方法是这样的:

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 - 尽管执行的任务不使用 token )看起来更像是滥用CancellationToken机制。这到底有多糟糕?根据流中确定的信息取消延续链的正确、“惯用”方法是什么?

(外部代码具有预期效果,但我认为就使用现有工具而言,这是解决任务的错误方法。我不是在寻找对我的“解决方案”的批评,而是在寻找正确的方法去做。这就是为什么我把它放在 SO 而不是代码审查上。)

最佳答案

对于延续,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/

相关文章:

c# - 这样显示菜单方便吗?

c# - 正则表达式 - 提取子串

c# - 启动画面 IOException

.net - MySQL DataCONnection 和 ADO.NET

c# - 引用的 System.Net.Http 程序集未复制到 dotnet msbuild 上的输出 bin\Release 目录

c# - Parallel 用于在循环时丢失值

c# - 如何将凭据传递给 SOAP Web 服务?

.net - Task.Wait()不包含任何链接的(ContinueWith)任务

c# - 等待完成所有异常处理任务

javascript - 在新窗口中打开链接