从GetSomethingAsync回调中返回对象

Tim*_*hel 2 c# task windows-phone-7 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;
}
Run Code Online (Sandbox Code Playgroud)

问题?我认为将返回类型更改为just GetTokenResult 可能会比动作更快地返回,因此我的结果永远不会被设置.我不能await使用异步方法,因为它返回void.

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

Jon*_*eet 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;
}
Run Code Online (Sandbox Code Playgroud)

当返回的任务将只完成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;
}
Run Code Online (Sandbox Code Playgroud)

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