我有一些异步方法:

// not ideal
private TaskCompletionSource<A> _tcsA;
private TaskCompletionSource<A> _tcsB;
private TaskCompletionSource<A> _tcsC;
...

public Task<A> GetAAsync() {
  _currentTask = TaskType.A;
  _tcsA = new TaskCompletionSource<A>();
  // some complex non-sync task, using http/events that ends with Complete();
  // QueueRequest?.Invoke(this, taskInfo); // raise request -- this does not return
  return _tcsA.Task;
}

public Task<B> GetBAsync() {
  _currentTask = TaskType.B;
  _tcsB = new TaskCompletionSource<B>();
  // some complex non-sync task, using http/events that ends with Complete();
  // QueueRequest?.Invoke(this, taskInfo); // raise request -- this does not return
  return _tcsB.Task;
}

public Task<C> GetCAsync() {
  _currentTask = TaskType.C;
  _tcsC = new TaskCompletionSource<C>();
  // some complex non-sync task, using http/events that ends with Complete();
  // QueueRequest?.Invoke(this, taskInfo); // raise request -- this does not return
  return _tcsC.Task;
}

// called by an external source, a http listener / processor
// this should complete the async call by the client and return results
public void Complete(Result result) {
  switch (_currentTask) {
    case TaskType.A:
      _tcsA.SetResult(new A());
      break;
    case TaskType.B:
      _tcsB.SetResult(new B());
      break;
    case TaskType.C:
      _tcsC.SetResult(new C());
      break;
  }

  _currentTask = TaskType.None;
}


为了简单起见,以上是半伪代码。我称这样的方法之一:

A a = await service.GetAAsync();

现在的问题是TaskCompletionSource<T>是泛型的,如果我有100种方法,则必须为每种返回类型创建一个变量。但是由于一次只能调用一种方法,因此最好使用单个TaskCompletionSource,而不是将其键入object (TaskCompletionSource<object>)

我不想做:

object a = await service.GetAAsync();

因为那将需要客户进行转换。因此,最好的解决方案是只有一个TaskCompletionSource,但以某种方式键入它。或者,也可以具有TaskCompletionSource词典。两者对我来说似乎都是不可能的。

我该如何解决?

更新:

有关我的情况的背景信息,请查看:Wrap synchronous code into async await in disconnected scenario

最佳答案

我不想执行object a = await service.GetAAsync(),因为这需要客户端进行转换。


不必要。保留相同的签名,但添加对ContinueWith的调用以强制转换为适当的类型:

public Task<A> GetAAsync() {
  _currentTask = TaskType.A;
  _tcs = new TaskCompletionSource<object>();
  // some complex task that ends with Complete();
  return _tcs.Task.ContinueWith(t => (A)t.Result);
}


或者,您可以使用async / await执行相同的操作:

public async Task<A> GetAAsync() {
  _currentTask = TaskType.A;
  _tcs = new TaskCompletionSource<object>();
  // some complex task that ends with Complete();
  return (A)await _tcs.Task;
}

07-28 13:35