C# Task.Factory.StartNew与异步方法

C# Task.Factory.StartNew与异步方法,c#,task-parallel-library,async-await,C#,Task Parallel Library,Async Await,这可能是一个微不足道的问题,但它可能有助于我的基本理解 以下两种实现之间有什么重要区别吗 Task.Factory.StartNew: public Task<string> ReadAllTextAsync(string path) { return Task.Factory.StartNew(() => File.ReadAllText(path)); } 是的,有一个关键的区别:Task.Factory.StartNew没有保留同步上下文,而在使用async/

这可能是一个微不足道的问题,但它可能有助于我的基本理解

以下两种实现之间有什么重要区别吗

  • Task.Factory.StartNew

    public Task<string> ReadAllTextAsync(string path) {
        return Task.Factory.StartNew(() => File.ReadAllText(path));
    }
    

  • 是的,有一个关键的区别:
    Task.Factory.StartNew
    没有保留同步上下文,而在使用async/await时,会保留此上下文。例如,在ASP.NET应用程序中,这意味着如果使用
    Task.Factory.StartNew
    任务内部可能无法访问HttpContext,而如果使用async/await,则HttpContext将可用


    与您提供的示例还有另一个重要区别。在第一种情况下,您使用的是阻塞API:
    File.ReadAllText(path)
    ,而在第二种情况下,您使用的是具有真正异步I/O操作的I/O完成端口。这意味着,在第一种情况下,在整个任务执行期间,您正在危及执行该任务的线程,而在第二种情况下,由于I/O完成端口,该线程是空闲的。

    @dtb,我们在处理任务时不能真正谈论线程池。第一个示例是阻塞执行任务的线程,而在第二个示例中则不是。我已经更新了我的答案以包含这些信息。谢谢,这澄清了它(特别是第二点,我怀疑IO中存在一些低效问题)。@DarinDimitrov同步上下文的差异是否主要是
    Task.Factory.StartNew
    wait
    使用的默认值的一个因素?如果我没有弄错的话,对waitiables上用于
    StartNew
    ConfigureAwait
    TaskScheduler
    的操作可能会导致它们使用相同的上下文。在这种情况下,仍然存在一些潜在的差异,但它们更加微妙。在更深入地研究了这个问题之后,我进一步相信这个答案可能会误导。它确实指出了实现1和实现2的区别,但这些并不是异步/等待模式与使用
    Task.Factory.StartNew
    之间的根本区别。读者很容易误解这个答案,认为它解释了任务和异步之间的根本区别(特别是给出了问题的标题)@达林迪米特罗夫-我建议您编辑以明确这一区别。我会亲自编辑,但如果有你更高的代表,我会感谢你的祝福。@Snixtor,根据你的说法,基本的区别是什么?请随意编辑我的答案。如果我不同意你的编辑,我会把它还原回来。
    public async Task<string> ReadAllTextAsync(string path) {
        using (var stream = File.OpenRead(path))
        using (var reader = new StreamReader(stream)) {
            return await reader.ReadToEndAsync();
        }
    }