首页 > 解决方案 > 如何避免异步方法使用新线程?

问题描述

我已经读过 await/async 不应该创建/使用新线程,但是编译器会在后台创建一个 astate 机器......所以我尝试了这个,并且每次调用 F1 都使用来自 ThreadPool 的线程。

class Program
{
    static System.Threading.SemaphoreSlim sem =
        new System.Threading.SemaphoreSlim(20, 20);
    static async void F1()
    {
        await sem.WaitAsync();
        await sem.WaitAsync();
        await Task.Delay(6000);
        var threadId = GetCurrentThreadId();
        sem.Release();
        sem.Release();
    }

    static void Main(string[] args)
    {
        var threadId = GetCurrentThreadId();

        F1();
        F1();
        F1();
        F1();
        F1();
        F1();
        F1();
        F1();
        Task.Delay(30000).Wait();
    }
    [DllImport("kernel32.dll")]
    static extern uint GetCurrentThreadId();

}

标签: c#.netasync-await

解决方案


您已经使用await Task.Delay(6000)了 ,它保证不会同步完成,因此:完成将通过任何可能的方式返回 - 通常是线程池(因为这里没有同步上下文)。线程池线程很便宜,只要不长期捆绑就行;如果它所做的只是捕获当前线程 id 并释放,它们应该在它们触发后立即完成。

代码需要在某处运行;您希望它在哪个线程上运行?您的主线程当前处于阻塞Wait()调用中,因此它无法执行任何操作。注意:您几乎不应该调用.Wait()不完整的Task.


推荐阅读