使用C#功能異步並等待您可以將異步流重寫爲類似於同步流的東西。你只提供你的代碼的一些片段,提供我創造了一些代碼,類似於你的代碼一個完整的例子:
class StartEventArgs : EventArgs {
public StartEventArgs(Int32 sessionId, Int32 errorCode) {
SessionId = sessionId;
ErrorCode = errorCode;
}
public Int32 SessionId { get; private set; }
public Int32 ErrorCode { get; private set; }
}
delegate void StartEventHandler(Object sender, StartEventArgs e);
class ServiceProvider {
public event StartEventHandler Start;
public void Startup(Boolean succeed) {
Thread.Sleep(TimeSpan.FromSeconds(1));
if (succeed)
OnStart(new StartEventArgs(321, 0));
else
OnStart(new StartEventArgs(0, 123));
}
protected void OnStart(StartEventArgs e) {
var handler = Start;
if (handler != null)
handler(this, e);
}
}
的ServiceProvider.Startup
方法將用於第二延遲觸發一個事件之前,要麼信號成功或失敗取決於提供的succeed
參數。該方法相當愚蠢,但有希望類似於您的方法的行爲。
您可以使用TaskCompletionSource
異步啓動轉換成一個任務:
Task<Int32> PerformStartup(ServiceProvider serviceProvider, Boolean succeed) {
var taskCompletionSource = new TaskCompletionSource<Int32>();
serviceProvider.Start += (sender, e) => {
if (e.ErrorCode > 0)
throw new Exception(e.ErrorCode.ToString());
taskCompletionSource.SetResult(e.SessionId);
};
serviceProvider.Startup(succeed);
return taskCompletionSource.Task;
}
通知由Start
事件標誌着一個錯誤是如何轉化爲Exception
(產品代碼中,你應該使用一個自定義異常類型,而不是)。
使用異步和等待的C#,你現在就可以編寫代碼,看起來功能非常像同步代碼即使它實際上是異步的:
async void Startup(Boolean succeed) {
var serviceProvider = new ServiceProvider();
try {
var sessionId = await PerformStartup(serviceProvider, succeed);
Console.WriteLine(sessionId);
}
catch (Exception ex) {
Console.WriteLine(ex);
}
}
如果由Start
事件報告了一個錯誤,你現在可以在catch
區塊處理。此外,會話ID只是該函數的返回值。 「魔術」是在Task
上使用await
將在任務完成時返回任務的結果,並且如果任務中引發異常,則可以在等待任務的線程上捕獲該異常。