如何在c#中将事件更改为不同的方法

时间:2015-05-28 08:59:30

标签: c# event-handling

我需要将我的活动分开作为一种不同的方法..但我使用的是TaskCompletionSource并且不知道我该怎么做?

这是我的代码

    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;
    }

我想这样做

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)
{
    .....
}

但问题是,如何用这种不同的方法返回任务。有时我有异常,因为当我下载因为这种事件时,我搜索时,建议将此事件分开..

我希望它清楚......

1 个答案:

答案 0 :(得分:1)

这里有一个捕获的变量tcs),编译器使用编译器生成的捕获上下文类来实现。您可以手动实现相同的东西(或类似的东西):

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]);
    }
}

作为咨询:我担心您永远不会删除service上的活动订阅;如果重新使用/保留service,这可能会产生令人讨厌的副作用。

请注意,有时您会将传入某个上下文传递给异步方法,在这种情况下您可以作弊,例如:

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]);
}