如何将任务转换 给任务 ?(How to convert a Task

2019-07-22 03:52发布

由于C#的任务是一类,你显然不能施放Task<TDerived>Task<TBase>

但是,你可以这样做:

public async Task<TBase> Run() {
    return await MethodThatReturnsDerivedTask();
}

是否有一个静态任务的方法我可以打电话获得一个Task<TDerived>实例,它本质上只是指向底层的任务,投下的结果? 我想是这样的:

public Task<TBase> Run() {
    return Task.FromDerived(MethodThatReturnsDerivedTask());
}

请问这样的方法存在吗? 是否有任何开销使用异步方法只用于此目的?

Answer 1:

请问这样的方法存在吗?

没有。

是否有任何开销使用异步方法只用于此目的?

是。 但是,这是最简单的解决方案。

需要注意的是一个更通用的方法是一个扩展方法Task ,如Then 。 斯蒂芬Toub探讨过这个在博客和我最近将其纳入AsyncEx 。

使用Then ,您的代码将是这样的:

public Task<TBase> Run()
{
  return MethodThatReturnsDerivedTask().Then(x => (TBase)x);
}

略少开销的另一种方法是创建自己的TaskCompletionSource<TBase>并将它与派生结果(使用完毕TryCompleteFromCompletedTask在我AsyncEx库):

public Task<TBase> Run()
{
  var tcs = new TaskCompletionSource<TBase>();
  MethodThatReturnsDerivedTask().ContinueWith(
      t => tcs.TryCompleteFromCompletedTask(t),
      TaskContinuationOptions.ExecuteSynchronously);
  return tcs.Task;
}

或者(如果你不想承担AsyncEx的依赖):

public Task<TBase> Run()
{
  var tcs = new TaskCompletionSource<TBase>();
  MethodThatReturnsDerivedTask().ContinueWith(t =>
  {
    if (t.IsFaulted)
      tcs.TrySetException(t.Exception.InnerExceptions);
    else if (t.IsCanceled)
      tcs.TrySetCanceled();
    else
      tcs.TrySetResult(t.Result);
  }, TaskContinuationOptions.ExecuteSynchronously);
  return tcs.Task;
}


Answer 2:

请问这样的方法存在吗? 是否有任何开销使用异步方法只用于此目的?

目前对此没有内置的方法,这也导致开销。

的“重量最轻”替代方案将是使用一个TaskCompletionSource<T>创建此新任务。 这可以通过像这样的扩展方法来完成:

static Task<TBase> FromDerived<TBase, TDerived>(this Task<TDerived> task) where TDerived : TBase
{
     var tcs = new TaskCompletionSource<TBase>();

     task.ContinueWith(t => tcs.SetResult(t.Result), TaskContinuationOptions.OnlyOnRanToCompletion);
     task.ContinueWith(t => tcs.SetException(t.Exception.InnerExceptions), TaskContinuationOptions.OnlyOnFaulted);
     task.ContinueWith(t => tcs.SetCanceled(), TaskContinuationOptions.OnlyOnCanceled);

     return tcs.Task;
}


Answer 3:

可以尝试这样: task.ContinueWith<TDerived>( t => (TDerived)t.Result);



文章来源: How to convert a Task to a Task?