2

我正在使用任务延续在 WinForm 项目上进行长时间运行的操作。

var task1 = Task.Factory.StartNew(() => DoSomeWork());

var task2 = task1.ContinueWith(result => DoSomeMoreWork(), TaskContinuationOptions.OnlyOnRanToCompletion);

var task3 = task2.ContinueWith(result => DoFinalWork(), TaskContinuationOptions.OnlyOnRanToCompletion);

如果在 task2 上执行的 DoSomeMoreWork() 函数满足某些条件,我只想继续执行 task3。如何才能做到这一点?

4

2 回答 2

1

来自MSDN

用户定义的值可以在 Result 属性中从前件传递给它的延续,这样前件的输出就可以作为延续的输入

所以一种方法是在任务 3 中,在做任何工作之前检查任务 2 的结果。

var task2 = task1.ContinueWith(result => DoSomeMoreWOrk(), TaskContinuationOptions.OnlyOnRanToCompletion);
var task3 = task2.ContinueWith(x => DoFinalWork(x.Result));

从 task2 返回的 Result 决定了 task3 中发生的情况。

编辑 如果在操作中不满足某些条件,另一个解决方案是取消 task2。然后甚至没有安排继续任务。

来自 MSDN

要防止在其前件被取消时继续执行,请在创建继续时指定 NotOnCanceled 选项。

所以task3定义变成

var task3 = task2.ContinueWith(result => DoFinalWork(), TaskContinuationOptions.NotOnCancelled);
于 2012-06-08T09:42:14.673 回答
1

另一种选择是将 task2 和 task3 转换为嵌套任务,仅在满足条件时执行它们。

假设 DoSomeMoreWork 返回 true 来执行此操作,您可以编写类似这样的内容

        var task1 = Task.Factory.StartNew(DoSomeWork);
        var task2 = task1.ContinueWith(result =>
            {
                if (DoSomeMoreWork())
                {
                    Task.Factory.StartNew(DoFinalWork, TaskCreationOptions.AttachedToParent);
                }
            }, TaskContinuationOptions.OnlyOnRanToCompletion);

如果您可以使用 Async CTP 或 .NET 4.5(我认为两者都有 Go Live 许可证),您可以用 async/await 替换延续,以获得更简洁的代码。

如果您将工作函数转换为使用异步,您的代码将变得几乎与同步版本一样清晰:

    private static async void WorkAsync()
    {
        await DoSomeWork();
        if (await DoSomeMoreWork())
        {
            await DoFinalWork();
        }
    }

    private static async Task DoFinalWork()
    {
        Console.WriteLine("Completed");
    }

    private static async Task<bool> DoSomeMoreWork()
    {
        Console.WriteLine("Some More");
        return true;
    }

    private static async Task DoSomeWork()
    {
        Console.WriteLine("Some");
    }

如果您不想从方法中返回任务,可以使用以下代码:

    private static async void WorkAsync()
    {
        await Task.Run(()=>DoSomeWork());
        if (await Task.Run(()=>DoSomeMoreWork()))
        {
            await Task.Run(()=>DoFinalWork());
        }
    }
于 2012-06-08T13:00:37.200 回答