Reputation: 1606
I need to separate my event as a different method.. But I am using TaskCompletionSource and don't know how can i do that?
Here is my code
public Task<byte[]> Download(DocumentProfile profile)
{
var tcs = new TaskCompletionSource<byte[]>();
service.DownloadLastVersionCompleted += (sender, args) =>
{
if (args.Error != null)
tcs.TrySetResult(null);
if (args.Result != null)
tcs.TrySetResult(args.Result);
else
tcs.TrySetResult(new byte[0]);
};
service.DownloadLastVersionAsync(profile);
return tcs.Task;
}
and I want to do like this
public Task<byte[]> Download(DocumentProfile profile)
{
var tcs = new TaskCompletionSource<byte[]>();
service.DownloadLastVersionCompleted+=OnDownloadCompleted;
service.DownloadLastVersionAsync(profile);
return tcs.Task;
}
private void OnDownloadCompleted(object sender, DownloadLastVersionCompletedEventArgs e)
{
.....
}
but here is the problem, how i can return task with that kind of different method. Sometimes I have exception because when I downloaded because of this kind of event, as I search, recommended to separate this event..
I hope its clear..
Upvotes: 1
Views: 53
Reputation: 1062520
What you have here is a captured variable (tcs
), which the compiler implements using a compiler-generated capture-context class. You can implement the same thing (or something similar) manually:
public Task<byte[]> Download(DocumentProfile profile)
{
var state = new DownloadState();
service.DownloadLastVersionCompleted += state.OnDownloadCompleted;
service.DownloadLastVersionAsync(profile);
return state.Task;
}
class DownloadState
{
private TaskCompletionSource<byte[]> tcs = new TaskCompletionSource<byte[]>();
public Task<byte[]> Task { get { return tcs.Task; } }
public void OnDownloadCompleted(
object sender, DownloadLastVersionCompletedEventArgs args)
{
if (args.Error != null)
tcs.TrySetResult(null);
if (args.Result != null)
tcs.TrySetResult(args.Result);
else
tcs.TrySetResult(new byte[0]);
}
}
As an advisory: I am concerned that you never remove the event subscription on service
; this could have nasty side-effects if service
is re-used / kept around.
Note that sometimes you get to pass in some context to an asynchronous method, in which case you can cheat, for example:
public Task<byte[]> Download(DocumentProfile profile)
{
var tcs = new TaskCompletionSource<byte[]>();
service.DownloadLastVersionCompleted += OnDownloadCompleted;
service.DownloadLastVersionAsync(profile, state: tcs);
return tcs.Task;
}
private void OnDownloadCompleted(
object sender, DownloadLastVersionCompletedEventArgs args)
{
var tcs = (TaskCompletionSource<byte[]>)args.State;
if (args.Error != null)
tcs.TrySetResult(null);
if (args.Result != null)
tcs.TrySetResult(args.Result);
else
tcs.TrySetResult(new byte[0]);
}
Upvotes: 1