await task.run vs await c#

我在网上搜索并看到很多关于task.run和等待异步的问题,但是有一个特定的使用场景,我并不是真的理解它们的区别。 我相信情景非常简单。

await Task.Run(() => LongProcess()); 

VS

 await LongProcess()); 

其中LongProcess是一个异步方法,其中包含一些异步调用,例如调用db并等待ExecuteReaderAsync()。

题:

这种情况下两者之间有什么区别吗? 任何帮助或输入赞赏,谢谢!

Task.Run 可以在不同的线程上发布要处理的操作。 这是唯一的区别。

这可能是有用的 – 例如,如果LongProcess不是真正的异步,它将使调用者返回更快。 但对于一个真正的异步方法,使用Task.Run是没有意义的,它可能会导致不必要的浪费。

但要小心,因为Task.Run的行为将根据重载Task.Run而改变。 在您的示例中,将选择Func重载,它将(正确地)等待LongProcess完成。 但是,如果使用了非任务返回的委托, Task.Run将只等待第一次await执行(请注意,这就是TaskFactory.StartNew始终如何运行,所以不要使用它)。

人们常常认为async-await是由几个线程完成的。 事实上,这一切都是由一个线程完成的。

请参阅下面有关此一个线程语句的添加内容

帮助我理解async-await的事情是Eric Lippert对async-await的采访 。 在中间的某个地方他比较异步等待与一个必须等​​待一些水沸腾的厨师。 他没有做任何事情,而是环顾四周,看看还有别的东西要做,比如切洋葱。 如果完成,水仍然没有沸腾,他会检查是否还有其他事情要做,等等,直到他无事可做,只能等待。 在那种情况下,他回到他等待的第一件事。

如果你的过程调用了一个等待函数,我们可以肯定,在这个等待函数的某个地方有一个等待函数的调用,否则函数将无法等待。 实际上,如果您忘记等待等待函数中的某个地方,您的编译器会发出警告。

如果你的等待函数调用另一个等待函数,则线程进入另一个函数并开始执行此函数中的操作并深入到其他函数,直到他遇到等待。

线程在他的调用堆栈中上升,而不是等待结果,看看是否有其他代码可以处理,直到他看到等待。 再次进入调用堆栈,进行处理直到等待等等。一旦每个人都在等待线程查找底部等待并继续一旦完成。

这样做的好处是,如果等待函数的调用者不需要函数的结果,但在需要结果之前可以做其他事情,那么这些其他事情可以由线程完成,而不是在函数内部等待。

没有立即等待结果的调用将如下所示:

 private async Task MyFunction() { TasktaskA = SomeFunctionAsync(...) // I don't need the result yet, I can do something else DoSomethingElse(); // now I need the result of SomeFunctionAsync, await for it: ReturnType result = await TaskA; // now you can use object result } 

请注意,在这种情况下,一切都由一个线程完成。 只要你的线程有事可做,他就会很忙。

加成。 事实上只涉及一个线程。 任何无所事事的线程都可能在等待之后继续处理您的代码。 如果检查线程ID,则可以看到在等待之后可以更改此ID。 持续线程与原始线程具有相同的context ,因此您可以将其视为原始线程。 无需检查InvokeRequired ,无需使用互斥锁或关键部分。 对于您的代码,这就好像涉及一个线程。

本答案末尾的文章链接解释了有关线程上下文的更多信息

您将看到等待其他进程必须执行操作的等待函数,而您的线程只需等待,直到另一个进程完成。 例如,通过互联网发送数据,保存文件,与数据库通信等。

但是,有时必须进行一些繁重的计算,并且您希望您的线程可以自由地执行其他操作,例如响应用户输入。 在那个桶中,您可以启动一个等待操作,就好像您调用了异步函数一样。

 Task LetSomeoneDoHeavyCalculations(...) { DoSomePreparations() // start a different thread that does the heavy calculations: var myTask = Task.Run( () => DoHeavyCalculations(...)) // now you are free to do other things DoSomethingElse(); // once you need the result of the HeavyCalculations await for it var myResult = await myTask; // use myResult ... } 

现在一个不同的线程正在进行繁重的计算,而你的线程可以自由地做其他事情。 一旦它开始等待你的呼叫者可以做的事情,直到他开始等待。 有效地,您的线程可以相当自由地对用户输入作出反应。 但是,只有每个人都在等待才会出现这种情况。 当您的线程忙于处理时,您的线程无法对用户输入做出反应。 因此,请始终确保如果您认为您的UI线程必须执行一些繁忙的处理需要一些时间使用Task.Run并让另一个线程执行它

另一篇帮助我的文章: Async-Await由出色的解释员Stephen Cleary提供