昨年、私は従来の同期メソッドと非同期メソッドを備えた Web API ライブラリを作成しました。新しいC# Async CTP 3を使用して TaskAsync メソッドを追加しようとしています。
sync メソッドをカプセル化するために、次の簡単なコードを書きました。
partial class Client : IClient {
public string Authenticate(string username, string password)
{
// long synchronous code here
}
public Task<string> AuthenticateTaskAsync(string username, string password) {
var p = new { username = username, password = password };
var task = new Task<string>(p1 => this.Authenticate(p.username, p.password), p);
return task;
}
}
次に、私の WPF 4 アプリケーションから、それを使用する非同期メソッドがあります。
public class LoginViewModel {
private IClient client;
// called by an ICommand
private async Task DoLogin(string username, string password) {
UpdateStatus("Authenticating...", true);
try {
var result = await client.AuthenticateTaskAsync(username, password);
// do stuff with result
UpdateStatus("Authenticated. Fetching User informations...", true);
} catch (Exception ex) {
UpdateStatus("Authentication error.", ex, false);
}
}
}
問題は、同期メソッドが呼び出されないことです。デバッガーは に移動しresult = await client.AuthenticateTaskAsync(username, password);
、デバッガーは作業を続行し、戻ってきません。同期内のブレークポイントがAuthenticate
壊れることはありません。UpdateStatus
呼び出されることはありません。かなり奇妙です(デバッガーの実装の問題でしたが)。
WebClient.DownloadStringTaskAsync
次に、実装方法を調べました。API クライアント メソッドを次のように変更しました。
partial class Client : IClient {
public Task<string> AuthenticateTaskAsync(string username, string password) {
var tcs = new TaskCompletionSource<string>();
try {
tcs.TrySetResult(this.Authenticate(username, password));
} catch (Exception ex) {
tcs.TrySetException(ex);
}
return tcs.Task;
}
}
そして今、それは機能します。最初のコードが機能しない理由を誰か説明できますか?