c# - 为什么我的代码在多个线程上运行?
问题描述
很长一段时间以来,我一直在尝试理解 .NET 中的 async-await 内容,但我很难成功,当我使用 async 时,总会发生一些完全出乎意料的事情。
这是我的应用程序:
namespace ConsoleApp3
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("Hello World!");
var work1 = new WorkClass();
var work2 = new WorkClass();
while(true)
{
work1.DoWork(500);
work2.DoWork(1500);
}
}
}
public class WorkClass
{
public async Task DoWork(int delayMs)
{
var x = 1;
await Task.Delay(delayMs)
var y = 2;
}
}
}
这只是我创建的一个示例,用于检查代码将如何执行。有几件事让我感到惊讶。首先,涉及到很多线程!如果我在上面设置断点,var y = 2;
我可以看到那里的 threadId 不一样,它可以是 1、5、6 或其他值。这是为什么?我认为 async/await 不会单独使用其他线程,除非我明确命令(通过使用 Task.Run 或创建新线程)。至少这篇文章试图说我认为。
好的,但是假设出于某种原因还有其他一些线程-即使它们是,我await Task.Delay(msDelay);
也没有ConfigureAwait(false)
!据我了解,没有这个调用,线程不应该改变。
我很难很好地掌握这个概念,因为我找不到任何可以包含所有信息而不仅仅是几条信息的好资源。
解决方案
当异步方法等待某事时,如果它不完整,它会安排一个延续然后返回。问题是继续在哪个线程上运行。如果存在同步上下文,则将安排继续在该上下文中运行 - 通常是 UI 线程,或者可能是特定的线程池。
在您的情况下,您正在运行一个控制台应用程序,这意味着没有同步上下文(SynchronizationContext.Current
将返回 null)。在这种情况下,延续在线程池线程上运行。并不是专门创建一个新线程来运行延续 - 只是线程池将获取延续,而“主”线程不会运行延续。
ConfigureAwait(false)
用于指示您不想返回到当前同步上下文以继续进行 - 但由于在您的情况下无论如何都没有同步上下文,因此没有区别。
推荐阅读
- python - Python pyglet 不停地重复播放音频
- php - 限制循环的数量,然后将其传递给下一个进程
- c# - c#指纹生物识别,UserConsentVerificationResult()无响应(WPF)
- dvc - 没有导入的派生数据的 DVC 依赖项
- python - 如何使用 Python 将 RGB565 字节数组转换为 RGB888 字节数组?
- c# - 如何首先打开一个窗口,而不是 WPF 中的 MainWindow(C#)
- javascript - 如何在javascript中的字符串内创建嵌套for循环
- metabase - 对远程服务器进行 REST API 调用 - 元数据库
- asp.net - ASP.NET 文件上传不会在更新面板中保留回发文件
- flutter - Flutter AnimatedList 与提供者模式