简体   繁体   English

我应该使用常规任务还是延续任务?

[英]Should I use a regular Task or a continuation Task?

Suppose the following method is defined: 假设定义了以下方法:

Task<TResult> DoStuffAsync() 
{
    // ...
}

Consider the following code (snippet 1): 考虑以下代码(代码段1):

void MyFunction()
{
    Task<TResult> task = DoStuffAsync();
    task.ContinueWith(async () => {
        TResult result = await task;
        // do stuff with result
    });
    // poll `task` status...
}

in comparison to the following code (snippet 2): 与以下代码(代码段2)相比:

void MyFunction() 
{
    Task<TResult> task = DoStuffAsync();
    Task.Run(async () => {
        TResult result = await task;
        // do stuff with result
    });
    // poll `task` status...
}

(Note how I do not care about the status of the lambda function (fire-and-forget). But I do care if it raises any exceptions.) (请注意,我不关心lambda函数的状态(即发即忘)。但是,我关心它是否引发任何异常。)

The first difference between the two options seems clear: in (snippet 1) the code in the lambda will only begin execution after DoStuffAsync() has completed, whereas in (snippet 2) the code in the lambda will attempt to begin execution immediately and proceed when DoStuffAsync() has completed. 这两个选项之间的第一个区别似乎很明显:在(片段1)中,lambda中的代码仅 DoStuffAsync()完成后才开始执行,而在(片段2)中,lambda中的代码将尝试立即开始执行并继续DoStuffAsync()完成时。

However, apart from this difference, when should you use ContinueWith and when should you use Task.Run ? 但是,除了这种区别之外,什么时候应该使用ContinueWith以及什么时候应该使用Task.Run What happens if an exception is raised in DoStuffAsync() or in the lambda function? 如果在DoStuffAsync()或lambda函数中引发异常,会发生什么情况? Will it be swallowed or is every potential exception guaranteed to be raised to a block where it can be handled? 会吞下它还是确保将每个潜在的异常引发到可以处理的地方?

In your first case there's no need for the lambda to be async . 在第一种情况下,不需要lambda async There is no need to await the task. 无需await任务。 You can just use Result because you know that the task has already completed by that point in time. 您可以只使用Result因为您知道该任务在该时间点之前已经完成。

For your second example, you're scheduling the thread pool thread to perform the creation of a state machine that will merely schedule some code to run when the task finishes. 对于第二个示例,您正在调度线程池线程以执行状态机的创建,该状态机将仅调度一些代码以在任务完成时运行。 There's no real need for this at all. 根本没有真正的需要。 The Task.Run is adding nothing here. Task.Run在此处未添加任何内容。

Most likely the method itself should be an async method: 该方法本身很可能应该是async方法:

private async Task MyFunction() {
    var result = await DoStuffAsync();
    // do stuff with result
}

All that said, while both of your solutions have a lot of superfluous work, both will propagate exceptions from your underlying work to the tasks that each operation computes (although you don't store that task anywhere in your first example, so you have no way of inspecting that task to see if it faulted). 综上所述,尽管两个解决方案都有很多多余的工作,但两者都会将异常从基础工作传播到每个操作所计算的任务(尽管您没有在第一个示例中将该任务存储在任何地方,因此您没有检查该任务以查看其是否失败的方法)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM