【问题标题】:Creating an async method in .NET 4.0 that can be used with "await" in .NET 4.5在 .NET 4.0 中创建可与 .NET 4.5 中的“await”一起使用的异步方法
【发布时间】:2012-03-23 09:43:57
【问题描述】:

我有一个在 .NET 4.0 和 VS2010 中使用 C# 的 .NET 项目。

我想做的是向我的库中添加一些异步重载,以便在 .NET 4.5 中使用 await 关键字的用户更轻松地进行异步编程。现在重载的方法是非异步的。我也不想自己使用任何异步方法,只需创建新方法并使其可用。

是否可以在 .NET 4.0 和 VS2010 中创建异步方法,如果可以,.NET 4.0 异步方法应该是什么样的?

因为我使用的是 VS2010,所以我无法访问“async”关键字,那么在 .NET 4.0 中模拟该行为需要做什么?例如,它是否需要返回任何特定类型,是否需要在方法内部发生任何代码以使其当前正在调用的非异步代码异步发生?

【问题讨论】:

    标签: c# .net async-await .net-4.5


    【解决方案1】:

    正如其他人所说,您首先要让方法返回TaskTask<TResult>。这足以await 其在 .NET 4.5 中的结果。

    要使您的方法尽可能适合未来的异步代码,请遵循Task-based Asynchronous Pattern document(也可使用on MSDN)中的指南。它提供命名约定和参数建议,例如,用于支持取消。

    对于你的方法的实现,你有几个选择:

    【讨论】:

    • 另外,我会添加在使用 VS 2012 或更高版本编译时使用 async/await 的明显可能性,或者通过使用框架实现、Microsoft.Bcl.Async 包实现,或者(仅供专家使用)滚动你自己的。
    • @JeanHominal:虽然async 方法绝对是最简单的方法,但它超出了这个问题的范围,因为操作仅限于VS2010。
    • 当用户要求 .NET 4.0 时,提供的答案是针对 .NET 4.5。
    • @hc1:不,答案是描述 4.0 中可用的方法(返回 Task/Task<TResult>Task.Factory.FromAsyncTaskCompletionSource<TResult>)。
    【解决方案2】:

    最简单的方法是返回TaskTask<T>。这样就够了。

    但是,这只有在您的方法真正异步执行时才有意义。

    我还建议您按照通常的模式命名它们,例如 AbcAsync(“Async”后缀)。您的调用者不会注意到与使用 C# 5 创建的异步方法有任何区别(因为没有)。

    提示:只是将异步添加到方法中没有任何作用。您的方法将按顺序执行并返回已完成的任务。使方法返回一个任务必须服务于特定目的 - 通常这样做是因为该方法固有地异步执行(如 Web 服务调用或文件 IO)。

    如果您的方法仅包含计算但没有 IO(或仅阻塞 IO),通常最好不要将其设为异步,因为这样做您将一无所获。异步方法并不总是在单独的线程上执行。如果最后一句话让您感到惊讶,您可能需要深入研究一下这个主题。

    【讨论】:

    • 我要重载的方法(添加了 Async 后缀)不是异步的。我读过的 .NET 4.5 示例似乎通过添加“async”关键字使方法自动异步。我想知道如何在 .NET 4.0 中复制它。我已经更新了我的问题,所以这更清楚了。
    • 我将我的回复编辑为答案。如果您只想在不同的线程上生成方法代码,请在调用者中使用 Task.Factory.StartNew。您无需为此更改方法。
    • @JamesNewton-King:异步方法总是返回 voidTaskTask<T>。从调用者的的角度来看,它如何返回TaskTask<T> 在很大程度上是无关紧要的。我认为值得你阅读更多关于异步方法真正做什么的内容。
    • “如果你的方法只包含计算但没有 IO(或只有阻塞 IO),通常最好不要让它异步,因为这样做你什么也得不到。”
    • @Chin 这样做你会得到什么?将其留给调用者来启动并行性或将计算移出 UI 线程。线程不是那种计算方法的业务。
    【解决方案3】:

    只要你返回一个以某种方式完成的任务(无论是在线程中还是异步),你就会支持异步模型..

    让任务异步执行是另一回事。如果您有权访问 async 关键字和 API,您可以简单地将您的方法基于对其他已提供的异步方法的异步调用。但在这种情况下,您必须手工制作异步任务。

    可能有更好的方法来做到这一点,但我能看到(并使用过)的最优雅的方法是利用System.Threading.Tasks.TaskCompletionSource 来构造一个任务,使用Begin/End 异步方法模型来执行无论您需要执行什么。然后,当您手头有结果时,使用您的完成源将其发布到先前构造的 Task 实例。

    它肯定是异步的,只是不像即将发布的那样花哨。

    免责声明:我不是这方面的专家。刚刚做了一些实验。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-21
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 2013-02-22
      相关资源
      最近更新 更多