[英]How to convert this code to async await?
我有很多像這樣的代碼:
var feed = new DataFeed(host, port);
feed.OnConnected += (conn) =>
{
feed.BeginLogin(user, pass);
};
feed.OnReady += (f) =>
{
//Now I'm ready to do stuff.
};
feed.BeginConnect();
如您所見,我使用通常的異步操作方式。 如何更改此代碼以使用async await
? 最好是這樣的:
public async void InitConnection()
{
await feed.BeginConnect();
await feed.BeginLogin(user, pass);
//Now I'm ready
}
您可以使用TaskCompletionSource<T>
將EAP(基於事件的異步模式)包裝到Tasks中。 目前尚不清楚如何處理DataFeed類中的錯誤和取消操作,因此您需要修改此代碼並添加錯誤處理( 示例 ):
private Task ConnectAsync(DataFeed feed)
{
var tcs = new TaskCompletionSource<object>();
feed.OnConnected += _ => tcs.TrySetResult(null);
feed.BeginConnect();
return tcs.Task;
}
private Task LoginAsync(DataFeed feed, string user, string password)
{
var tcs = new TaskCompletionSource<object>();
feed.OnReady += _ => tcs.TrySetResult(null);
feed.BeginLogin(user, pass);
return tcs.Task;
}
現在您可以使用以下方法:
public async void InitConnection()
{
var feed = new DataFeed(host, port);
await ConnectAsync(feed);
await LoadAsync(feed, user, pass);
//Now I'm ready
}
注意 - 您可以將這些異步方法移動到DataFeed類。 但是,如果您可以修改DataFeed,那么最好使用TaskFactory.FromAsync
將APM API包裝到Tasks。
遺憾的是,沒有非泛型的TaskCompletionSource
會返回非泛型Task
所以通常的解決方法是使用Task<object>
。
您需要更改DataFeed
類以支持它。 你只需要在那里使用任務異步模式。 這意味着DataFeed
中的所有異步方法都必須返回一個Task
(或一些Task<T>
),並且它們應該被命名為ConnectAsync
(例如)。
現在,使用Socket
,這並不容易,因為Socket
上的XXXAsync
方法實際上並不等待! 最簡單的方法是TcpListener
使用TcpClient
和TcpListener
(假設您使用的是TCP):
public async Task<bool> LoginAsync(TcpClient client, ...)
{
var stream = client.GetStream();
await stream.WriteAsync(...);
// Make sure you read all that you need, and ideally no more. This is where
// TCP can get very tricky...
var bytesRead = await stream.ReadAsync(buf, ...);
return CheckTheLoginResponse(buf);
}
然后從外面使用它:
await client.ConnectAsync(...);
if (!(await LoginAsync(client, ...))) throw new UnauthorizedException(...);
// We're logged in
這只是示例代碼,我假設您實際上能夠編寫合適的TCP代碼。 如果你這樣做,使用await
異步編寫它並不是很難。 只是確保你總是在等待一些異步I / O操作。
如果你想只使用Socket
做同樣的事情,你可能不得不使用Task.FromAsync
,它提供了一個圍繞BeginXXX
/ EndXXX
方法的包裝器 - 非常方便。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.