【问题标题】:Cast a Task<T> to a T将 Task<T> 强制转换为 T
【发布时间】:2014-08-07 05:43:15
【问题描述】:

如何将Task&lt;IEnumerable&lt;IMapLocationItem&gt;&gt; 转换为IEnumerable&lt;IMapLocationItem&gt;

这是我得到Task&lt;IEnumerable&lt;IMapLocationItem&gt;&gt;的代码:

public async Task<IEnumerable<IMapLocationItem>> GetAllMapLocationItemsFromUserName(string userName)
{
    IEnumerable<IMapLocationItem> mapLocationImageGalleries = await db.mapLocationImageGalleries.Where(m => m.userName.Equals(userName)).ToListAsync();
    IEnumerable<IMapLocationItem> mapLocationVideoGalleries = await db.mapLocationVideoGalleries.Where(m => m.userName.Equals(userName)).ToListAsync();

    IEnumerable<IMapLocationItem> mapLocationItemsCombined = mapLocationImageGalleries.Concat(mapLocationVideoGalleries);
    return mapLocationItemsCombined;
}

我可以使用关键字.Result,但我在某处读到这会阻止async 任务异步,并且在使用Result 关键字时此方法需要很长时间才能完成。

Task&lt;IEnumerable&lt;IMapLocationItem&gt;&gt; 转换为IEnumerable&lt;IMapLocationItem&gt; 的最佳方式是什么?

提前致谢

【问题讨论】:

  • 为什么不能在调用GetAllMapLocationItemsFromUserName的函数中使用await关键字?
  • 它会中断异步,因为调用者不等待函数完成。要强制执行此操作,您可以使用 await。

标签: c# asynchronous casting ienumerable


【解决方案1】:

来自 MSDN 网站http://msdn.microsoft.com/en-us/library/hh191443.aspx

 // Signature specifies Task<TResult>
 async Task<int> TaskOfTResult_MethodAsync()
 {
     int hours;
     // . . .
     // Return statement specifies an integer result.
     return hours;
 }

 // Calls to TaskOfTResult_MethodAsync
 Task<int> returnedTaskTResult = TaskOfTResult_MethodAsync();
 int intResult = await returnedTaskTResult;
 // or, in a single statement
 int intResult = await TaskOfTResult_MethodAsync();

您不能将任务强制转换为结果。这违背了异步的目的。上面的代码做的是异步调用函数,然后在代码中通过调用“await”请求结果。这将等待 asnyc 函数完成(将阻塞代码直到完成),直到结果准备好。

问题是当异步运行时你无法预测什么时候会完成,所以当我们最终准备好等待结果时,我们会告诉任务。它可以立即完成,也可以在 5 分钟内完成。只要函数需要完成,Await 就会等待。

【讨论】:

    【解决方案2】:

    您不能将Task&lt;T&gt; 转换为T,它们代表不同的东西。 Task&lt;T&gt; 表示将来最终将返回 T 的任务。如果你想获得任务的结果,你有几个选择(假设t = Task&lt;T&gt;

    • t.Result 阻止执行,直到结果可用。这会带来不幸的副作用,即在某些情况下可能会死锁,尤其是在与 UI 线程中的 async 方法结合使用时。
    • await t 安排一个延续并在结果可用时运行它。仅适用于 C# 5 和 .NET 4.5 或带有 Microsoft.Bcl.Async 库的 .NET 4。
    • t.ContinueWith 安排一个延续并在结果可用时运行它。

    一般我更喜欢使用awaitContinueWith,但有时使用Result是最简单的,特别是如果您可以访问调用和被调用方法的源,从而可以确保没有死锁发生。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多