【问题标题】:Task.Factory.StartNew vs Async methodsTask.Factory.StartNew 与异步方法
【发布时间】:2013-02-04 20:35:27
【问题描述】:

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

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

  1. Task.Factory.StartNew

    public Task<string> ReadAllTextAsync(string path) {
        return Task.Factory.StartNew(() => File.ReadAllText(path));
    }
    
  2. StreamReader 上的异步方法:

    public async Task<string> ReadAllTextAsync(string path) {
        using (var stream = File.OpenRead(path))
        using (var reader = new StreamReader(stream)) {
            return await reader.ReadToEndAsync();
        }
    }
    

【问题讨论】:

    标签: c# task-parallel-library async-await


    【解决方案1】:

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

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

    【讨论】:

    • @dtb,我们在处理任务时不能真正谈论线程池。第一个示例阻塞了任务执行所在的线程,而在第二个示例中它没有。我已更新我的答案以包含此信息。
    • 谢谢你,澄清了(尤其是第二点,我怀疑IO效率低下)。
    • @DarinDimitrov 同步上下文的差异在很大程度上不是Task.Factory.StartNewawait 使用的默认值 的一个因素吗?如果我没记错的话,对用于等待对象的StartNewConfigureAwaitTaskScheduler 进行操作可能会导致它们使用相同的上下文。在这种情况下,仍然存在一些潜在的差异,但它们更加微妙。
    • 在更深入地研究了这个问题之后,我进一步相信这个答案可能会产生误导。它确实指出了实现 1 和 2 中的差异,但这些不是异步/等待模式与使用Task.Factory.StartNew 之间的根本差异。读者很容易将这个答案误解为解释 Tasks 和 asyncs 之间根本区别的答案(尤其是考虑到问题标题)。 @DarinDimitrov - 我建议您进行编辑以明确区分。我会自己进行编辑,但如果您有更高的代表,将不胜感激。
    • @Snixtor,你认为根本的区别是什么?随意编辑我的答案。如果我不同意您的修改,我会将其还原。
    猜你喜欢
    • 1970-01-01
    • 2017-01-11
    • 2015-10-28
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多