AFAIK, all it knows is that at some point, its SetResult
or SetException
method is being called to complete the Task<T>
exposed through its Task
property.
In other words, it acts as the producer for a Task<TResult>
and its completion.
I saw here the example:
If I need a way to execute a Func asynchronously and have a Task to represent that operation.
public static Task<T> RunAsync<T>(Func<T> function)
{
if (function == null) throw new ArgumentNullException(“function”);
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
T result = function();
tcs.SetResult(result);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
Which could be used *if I didn’t have Task.Factory.StartNew
-
But I do have Task.Factory.StartNew
.
Question:
Can someone please explain by example a scenario related directly to TaskCompletionSource
and not to a hypothetical situation in which I don't have Task.Factory.StartNew
?
I mostly use it when only an event based API is available (for example Windows Phone 8 sockets):
public Task<Args> SomeApiWrapper()
{
TaskCompletionSource<Args> tcs = new TaskCompletionSource<Args>();
var obj = new SomeApi();
// will get raised, when the work is done
obj.Done += (args) =>
{
// this will notify the caller
// of the SomeApiWrapper that
// the task just completed
tcs.SetResult(args);
}
// start the work
obj.Do();
return tcs.Task;
}
So it's especially useful when used together with the C#5 async
keyword.