您好,对于这个话题的问题,我很抱歉,因为关于这些关键字的文章数量相当多,但也许这么多的文章让我陷入了某种误解。
我只想知道我是否正确理解了所有内容,并向竞选活动提出了几个问题。
- 让我们从async开始。标记为 async 的方法允许我们在此方法中使用 await,并要求返回类型具有 GetAwaiter 方法。
- 等待关键字。Await 放在辅助线程中执行的操作之前。它允许您不要等到辅助线程(IO 或常规线程)完成其执行。Await 只是将 await 之后的内容包装在一个单独的方法中,该方法在辅助线程完成时由回调调用。因此,主线程继续进一步执行。并且当辅助线程完成后,会从线程池中随机取出一个线程,完成方法的第二部分。
总的来说,它在应用程序中提供了什么
- 在带有 ui 线程的应用程序中(不完全清楚什么样的 ui 线程,我只使用 asp.net),我们的线程将继续运行并且不会阻塞用户操作;
- 在 asp.net mvc 中,我的主线程将被释放,只有辅助线程可以工作;
- 以及隐藏所有执行此操作的逻辑的最后一个语法糖。
问题
- 我是否正确描述了所有内容,这真的是异步等待的重点吗(将方法分成两部分并将第二部分作为回调执行,从而不会延迟主线程)?
- 什么是configureawait方法?
- 为什么很多人说这些关键词与流无关。那么,如何将 await 放在将在辅助线程中执行的操作之前,关键是,这种设计是为了不保留主线程而发明的。所以这里的联系是最直接的还是我错了?
- 当辅助线程完成执行时,哪个线程将继续执行方法的第二部分。同一个二级流?或者线程池中的任何线程都会被占用吗?
首先,你的假设。
嗯,从技术上讲,是的。但是还有一件更重要的事情要理解:使用关键字,
async函数被分成几部分,因此在这些部分之间,函数根本不会在任何地方运行。并且每个部分都是同步执行的,就像一个普通的函数一样。这些碎片的边界是沿着await。“等待被放置在在辅助线程上运行的操作之前。” - 这是不正确的,
await它仅表示此时函数停止执行,并Task在与其执行相关await的 结束时恢复。Task,正如我们已经看到的,根本不意味着“在某个线程中运行的一段代码”。例如,async-function 产生Task,它只是偶尔在特定线程中以块的形式运行。现在,你的问题。
一般来说,是的,但不是在一个部分,而是在许多方面。例如,想象一下这段代码:
在这个方法中,我们有
k + 1一个块,其中k是从 中获取的元素的数量IEnumerable<int>。如果
await在 UI 线程(或在任何拥有自己的TaskScheduler/的线程上SynchronizationContext)执行,则函数的下一部分将被扔到同一个 / 线程执行SynchronizationContext。如果你不需要它,你可以说ConfigureAwait(false),这意味着“我不在乎async-function 的其余部分在什么上下文中运行”。同时,运行时可以让它们在任何地方运行,没有任何保证。不,完成的操作
await不一定会在不同的线程上执行。Task不是“在其他地方执行的一段代码”。如果这个操作实际上并没有阻塞当前线程,那么是的,当前线程将是空闲的。但是您可以轻松编写Task,这将阻塞当前线程:在哪里以及如何进行
Task,完全由他自己决定Task。Task它完全在侧线程上执行的唯一情况是Task运行时Task.Run()(在这种情况下,线程是从线程池中获取的)。在其他情况下,决定在哪里执行是Task'e'的责任,async/await不关心它,甚至不要求Task它在任何地方执行。Task应该完成,是的(即使这样也不是必需的),但它可以在任何地方执行。这是一个例子:是的,一定要阅读这个问题的答案。