【发布时间】:2019-03-29 09:46:31
【问题描述】:
我有一些异步方法:
// 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
【问题讨论】:
-
看看generic type parameters他们可能会帮助你
-
没有任何非通用 API 用于此,因此您拥有的最佳选择确实是使用
object用于 TCS。对不起。 -
看看这个thread 和批准的答案
-
@PavelAnikhouski 这不是一回事;在 那个 的情况下,result 是非泛型的 (
Task)。在 this 情况下,输入结果 -Task<A>、Task<B>等,问题是 OP 只需要 TCS 的一个字段(因为它不希望处理多个并发操作),但 TCS 本质上是类型化/通用的 -
@MarcGravell 或者...我也很高兴能够将 TCS 对象添加到集合中,同时保持类型安全。我知道这是一个类似的问题。
标签: c# generics casting async-await taskcompletionsource