C# 异步IO API调用后在异步方法中的多个并发线程上继续

C# 异步IO API调用后在异步方法中的多个并发线程上继续,c#,.net,multithreading,async-await,C#,.net,Multithreading,Async Await,如果我有这个 static void Main(string[] args) { var tasks = new List<Task>(); for (int i = 0; i < 10; i++) { tasks.Add(AsyncWithBlockingIO(i)); } Task.WaitAll(tasks.ToArray()); } private static async Task AsyncWithBloc

如果我有这个

static void Main(string[] args)
{
    var tasks = new List<Task>();
    for (int i = 0; i < 10; i++)
    {
        tasks.Add(AsyncWithBlockingIO(i));
    }

    Task.WaitAll(tasks.ToArray());
}

private static async Task AsyncWithBlockingIO(int fileNum)
{
    var result = await File.ReadAllTextAsync($"File{fileNum}").ConfigureAwait(false);
    //will the below run concurrently on multiple threads?
    CpuNoIOWork(result);
}
当IO调用完成时,CpuNoIOWork是否会使用线程池在多个线程上并发运行,还是一次只使用一个线程

当IO调用完成时,CpuNoIOWork是否会使用线程池在多个线程上并发运行,还是一次只使用一个线程

它将在线程池线程上并发运行

但是,根据等待的内容的内部结构,它可能会在I/O线程池线程上继续,这是不可取的。如果您有CPU绑定的工作,我建议将其包装在Task.Run中,这将确保工作将在工作线程池线程上运行:

var result = await File.ReadAllTextAsync($"File{fileNum}").ConfigureAwait(false);
await Task.Run(() => CpuNoIOWork(result));

您可以添加Debug.WriteLineThread.CurrentThread.ManagedThreadId;为了证明continuations确实都是并发运行的,您可能想看看这一点:并不是所有的异步广告方法都是真正异步的。@TheodorZoulias,谢谢!在真正的代码中不使用文件API,但知道它很有用。而不是等待任务。在这种特定情况下运行,将等待任务。Yield强制继续在线程池线程上运行?@JohanP:是的,但我更喜欢Task.Run,以便代码更显式。@JohanP任务。Yield是一个穷人替代不存在的API。Task.Yield的行为取决于ambient SynchronizationContext.Current或ambient TaskScheduler.Current(如果上下文为null),因此切换到线程池不是可靠的平台无关方式,如果这是您的意图,@TheodorZoulias您会在.NETCore中说,在这个特定的实例中,这是一种可靠的方法来访问线程池线程吗?@JohanP不,我不会。我认为这不是适合这份工作的工具。如果我真的想避免这个任务。出于某种原因,我会使用一个定制的等待器,比如noseratio,或者它的简化版本。