I have some async methods:
// 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;
}
The above is semi-pseudo code for simplicity. I call one of the methods like so:
A a = await service.GetAAsync();
Now the problem is the TaskCompletionSource<T>
is generic, if I have a 100 methods in this way I would have to create a variable for each return type. But since only one method can be called at once it would be nice to use a single TaskCompletionSource
, yet not type it to object (TaskCompletionSource<object>)
.
I don't want to do:
object a = await service.GetAAsync();
Because that will need casting by the client. So the best solution would be to have a single TaskCompletionSource
, but have it typed somehow. Or alternatively be able to have a Dictionary of TaskCompletionSource
. Both of which seem impossible to me.
How should I solve this?
For a background on my situation have a look at: Wrap synchronous code into async await in disconnected scenario
I don't want to do
object a = await service.GetAAsync()
because that will need casting by the client.
Not necessarily. Keep the same signature, but add a call to ContinueWith
to cast to the appropriate type:
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);
}
Or you can do the same thing using 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;
}