无法理解异步和等待的需求[重复]
Posted
技术标签:
【中文标题】无法理解异步和等待的需求[重复]【英文标题】:Trouble understanding need for async and await [duplicate] 【发布时间】:2017-12-15 04:22:37 【问题描述】:昨天,我学习了有关 C# 多任务处理的基础知识。虽然我在技术上似乎理解它是如何工作的,但我只是不明白为什么它会像现在这样完成。请记住,我是该主题的新手,这可能表明我理解错误。例如,你可以写:
public async Task SomeEventHandler()
if(foo) return await SomeMethod("a");
else return await SomeMethod("b");
async Task<int> SomeMethod(string whatever)
string bar = await SomeInput();
return bar + " " + whatever;
我在这里没有看到为什么需要 async 和 await 关键字?为什么不能写:
public void SomeEventHandler()
if(foo) return SomeMethod("a");
else return SomeMethod("b");
int SomeMethod(string whatever)
string bar = SomeInput();
return bar + " " + whatever;
输入法实现类似于:
public string SomeInput()
while(!InputObject.stuffIncoming)
CurrentTheard.DoSomethingElse();
return InputObject.Next();
有人可以解释为什么这不起作用,或者会以不受欢迎的方式起作用吗?编辑:根据答案,似乎由于某种原因,等待的方法不能像常规方法那样被调用,反之亦然。但是是什么原因造成的呢?至少在 D 中,你可以为同一个函数调用或生成一个 theard。
【问题讨论】:
blogs.msdn.microsoft.com/ericlippert/2010/11/11/… 相关:How and When to useasync
and await
MSDN 很好地解释了 async/await
背后的含义。至于你的问题,试试吧。将Sleep(10000)
添加到SomeInput
中,看看有没有async/await
会发生什么。
嗯,还是没完全理解,但是好一点是的。感谢您的帮助。
await
是关于释放当前线程。您建议的替代方案本质上是一个嵌套消息循环。嵌套消息循环的问题是: 1) 它们会导致意外的重入(这就是俗语“DoEvents is evil”背后的原因)。 2) 库很难知道运行什么样的循环。 3)当没有消息循环(例如,线程池线程或控制台主线程)时,它们没有办法工作。
【参考方案1】:
async 和 await 背后的理念是提供一种简单的方法来实现“带有回调的并行执行”方法。每当使用关键字await
时,下一行代码的执行都会延迟,直到当前行完成(就像在正常执行中一样)但当前Thread
不会被阻塞。这意味着在幕后发生了以下事情:
-
您使用
await
调用长时间运行的操作
长时间运行的操作在另一个Thread
中执行
其余方法代码注册为回调方法
调用Thread
在方法开始长时间运行操作后继续执行
长时间运行的操作最终完成
回调方法(从第 3 点开始)被执行
这样做的好处是,您的代码将保持易于阅读。您不必为Threads
和回调而烦恼
【讨论】:
值得明确指出,为了获得这个好处,底层操作实际上必须是异步的——你不能随意地将它应用于任何操作(这个问题似乎暗示await
/non-await
可以随意换掉)。
所以它为每个等待的呼叫使用不同的 theard?但是这里有什么意义呢?为什么它必须为每个调用必须这样做的方法的方法将工作推到某个地方,而不仅仅是低级 i/o 函数这样做?
Ant P 是的,我就是这么想的,但为什么他们不能呢?
@RomanoZumbé 说“长时间运行的操作在另一个线程中执行”是一种误导,因为通常(例如大多数异步 IO)它不在另一个线程中执行。
您如何检查FileStream.WriteAsync
之类的线程ID?它返回 Task 但在其中没有任何地方可以切换到不同的线程。 “每个任务都衍生出另一个线程”是不正确的,任务和线程是不同的概念。以上是关于无法理解异步和等待的需求[重复]的主要内容,如果未能解决你的问题,请参考以下文章