从GetSomethingAsync回调中返回对象

时间:2013-07-02 15:16:36

标签: c# windows-phone-7 task async-await

我使用DropNet API连接到DropBox。我正在努力解决异步/等待概念。

我有一个方法是调用api GetTokenAsync。返回类型为void,并且存在成功和失败操作以进行回调。

public async Task<GetTokenResult> GetAuthorizationUrl()
{
    var result = new GetTokenResult();

    _dropNetClient.GetTokenAsync(
        login =>
            {
                result.Url = _dropNetClient.BuildAuthorizeUrl(_authorizationCallback.ToString());
                result.Success = true;
            },
        exception =>
            {
                result.Error = exception.ToDiagnosticString();
                result.Success = false;
            }
        );

    return result;
}

问题?我认为将返回类型更改为仅GetTokenResult 可能返回的速度比操作更快,因此我的结果永远不会被设置。我不能await async方法,因为它返回void。

这是围绕async / await的一个概念,我无法解决这个问题。

1 个答案:

答案 0 :(得分:6)

您可能需要考虑使用TaskCompletionSource

public Task<GetTokenResult> GetAuthorizationUrl()
{
    var tcs = new TaskCompletionSource<GetTokenResult>();   
    _dropNetClient.GetTokenAsync(
        login => tcs.SetResult(new GetTokenResult { 
            Url = _dropNetClient.BuildAuthorizeUrl(
                      _authorizationCallback.ToString()),
            Success = true
        },
        exception => tcs.SetResult(new GetTokenResult { 
            Error = exception.ToDiagnosticString(),
            Success = true
        });
    return tcs.Task;
}

返回的任务仅在GetTokenAsync操作完成后(通过其中一个回调)完成,您可以从异步方法等待它。

我个人会在失败时使用SetException代替SetResult - 所以如果你等待返回的任务,它会在异常上抛出适当的失败,而不是仅仅设置不同的值。它更像是习惯性的.NET。

编辑:然后您可以更改代码以返回Task<string>

public Task<string> GetAuthorizationUrl()
{
    var tcs = new TaskCompletionSource<string>();   
    _dropNetClient.GetTokenAsync(
        login => tcs.SetResult(_dropNetClient.BuildAuthorizeUrl
                                    _authorizationCallback.ToString()),
        exception => tcs.SetException(exception));
    return tcs.Task;
}

现在,异常将在任务本身内传播 - 如果await任务出现故障,则会在该点抛出异常。不需要额外的属性等 - 它更接近你编写相应的同步代码的方式。