2

我正在使用DropNet API 连接到 DropBox。不过,我在 async/await 概念上苦苦挣扎。

我有一个方法是调用 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;
}

问题?我在想将返回类型更改为 justGetTokenResult 可能会比操作返回得更快,因此我的结果永远不会被设置。我不能await使用异步方法,因为它返回 void。

这是关于 async/await 的一个概念,我无法理解。

4

1 回答 1

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的任务出错,则在该点引发异常。不需要额外的属性等 - 它更接近于您编写相应同步代码的方式。

于 2013-07-02T15:21:38.830 回答