gpt4 book ai didi

c# - C#异步而不创建新线程

转载 作者:行者123 更新时间:2023-12-03 13:15:13 25 4
gpt4 key购买 nike

我看过很多文章,解释了C#中的async/await不会像这样创建新线程:tasks are still not threads and async is not parallel。我想自己测试一下,所以编写了以下代码:

private static async Task Run(int id)
{
Console.WriteLine("Start:\t" + id + "\t" + System.Threading.Thread.CurrentThread.ManagedThreadId);

System.Threading.Thread.Sleep(500);

Console.WriteLine("Delay:\t" + id + "\t" + System.Threading.Thread.CurrentThread.ManagedThreadId);

await Task.Delay(100);

Console.WriteLine("Resume:\t" + id + "\t" + System.Threading.Thread.CurrentThread.ManagedThreadId);

System.Threading.Thread.Sleep(500);

Console.WriteLine("Exit:\t" + id + "\t" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}

private static async Task Main(string[] args)
{
Console.WriteLine("Action\tid\tthread");

var task1 = Run(1);
var task2 = Run(2);

await Task.WhenAll(task1, task2);
}

出乎意料的是,我最终得到的输出看起来像这样:
Action  id      thread
Start: 1 1
Delay: 1 1
Start: 2 1
Resume: 1 4 < ------ problem here
Delay: 2 1
Exit: 1 4
Resume: 2 5
Exit: 2 5

从我的角度来看,它确实是在创建新线程,甚至允许两段代码同时运行?我需要在非线程安全的环境中使用async/await,所以我不能让它创建新线程。为什么当前正在运行任务“2”时允许任务“1”继续执行(在 Task.Delay之后)?

我尝试将 ConfigureAwait(true)添加到所有 await中,但没有任何改变。

谢谢!

最佳答案

第一个问题-异步/等待不会自己创建线程,这与您期望的说法有很大不同-代码使用异步/等待时永远不会创建线程。

在您的特定情况下,安排延迟返回的计时器代码是选择线程池线程来运行其余代码。请注意,如果您使用的环境具有非空的同步上下文(如链接文章中的WPF),则在延迟后继续执行的代码将返回到原始线程,并在此时等待其他任务/主代码运行。

第二点-如何确保非线程安全对象不会从其他线程访问:您真的必须知道什么操作可以触发代码在其他线程上运行。 IE。 System.Timers.Timer可以做到这一点,即使它看起来不像创建线程。在保证执行将在同一线程(WinForms/WPF)或一次至少只有一个线程(ASP.Net)继续执行的环境中使用async/await可以使您在大多数情况下到达那里。

如果需要更强的保证,则可以遵循WinForms/WPF方法,该方法强制将对方法的访问权放在同一线程(称为主UI线程)上,并提供在异步上下文中使用async/await的指导,以确保在同一线程上继续执行它是await编写的(并且还直接提供Invoke功能供其他人自己管理线程)。这可能需要使用一些“线程强制”代理包装您不拥有的类。

关于c# - C#异步而不创建新线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58139217/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com