2013-07-02 54 views
2

我正在使用DropNet API連接到DropBox。儘管如此,我正在爲異步/等待概念而努力。從GetSomethingAsync回調中返回對象

我有一個方法是調用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。

這是圍繞異步/等待的一個概念,我無法環繞我的頭。

回答

6

你可能要考慮使用TaskCompletionSource:當GetTokenAsync操作完成(通過回調之一)

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

返回的任務將只完成了,你可以從一個異步方法等待着它。

雖然我會親自使用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一個該故障的任務,除了在這一點上拋出。不需要額外的屬性等 - 它更接近你如何編寫相應的同步代碼。

+0

謝謝喬恩。你能否給我一個使用這個方法和SetException的例子?我不明白,看看你會在哪裏消費這個例外。在這個方法的調用者中,我假設你想等待GetAuthorizationUrl(),它將刪除GetTokenResult並不再是任務。 –

+0

@TimGabrhel:「刪除GetTokenResult並不再是任務」是什麼意思?是的,您將等待'GetAuthorizationUrl' - 但如果您使用'tcs.SetException(exception)'而不是讓您的GetTokenResult具有錯誤/成功屬性,則意味着您可以捕捉異常,或者讓它傳播除此以外。哎呀,你甚至可以改變只使用'任務'作爲唯一的*成功*你返回的信息是一個字符串。 –

+0

我對這個例外的使用感到茫然。你是說你必須在這個方法中使用這個異常嗎?就我而言,我想將異常傳播回UI(WindowsPhone),以便我可以允許用戶通過電子郵件發送包含異常詳細信息的錯誤報告。因爲我想傳播,所以如果由於await關鍵字而導致調用方的實際返回類型是GetTokenResult,那麼我錯過了如何返回異常詳細信息的概念。 –