私は WCF にいくつかの外部 Web サービスを使用する Web サービスを持っているので、このサービスを非同期にしてスレッドを解放し、すべての外部サービスの完了を待ってから、結果をクライアントに返します。 .
フレームワーク 4.0 で
public class MyService : IMyService
{
public IAsyncResult BeginDoWork(int count, AsyncCallback callback, object serviceState)
{
var proxyOne = new Gateway.BackendOperation.BackendOperationOneSoapClient();
var proxyTwo = new Gateway.BackendOperationTwo.OperationTwoSoapClient();
var taskOne = Task<int>.Factory.FromAsync(proxyOne.BeginGetNumber, proxyOne.EndGetNumber, 10, serviceState);
var taskTwo = Task<int>.Factory.FromAsync(proxyTwo.BeginGetNumber, proxyTwo.EndGetNumber, 10, serviceState);
var tasks = new Queue<Task<int>>();
tasks.Enqueue(taskOne);
tasks.Enqueue(taskTwo);
return Task.Factory.ContinueWhenAll(tasks.ToArray(), innerTasks =>
{
var tcs = new TaskCompletionSource<int>(serviceState);
int sum = 0;
foreach (var innerTask in innerTasks)
{
if (innerTask.IsFaulted)
{
tcs.SetException(innerTask.Exception);
callback(tcs.Task);
return;
}
if (innerTask.IsCompleted)
{
sum = innerTask.Result;
}
}
tcs.SetResult(sum);
callback(tcs.Task);
});
}
public int EndDoWork(IAsyncResult result)
{
try
{
return ((Task<int>)result).Result;
}
catch (AggregateException ex)
{
throw ex.InnerException;
}
}
}
ここでの私の質問は次のとおりです。
このコードは 3 つのスレッドを使用しています。1 つは BeginDoWork でインスタンス化され、もう 1 つはコードが匿名メソッド ContinueWhenAll 内に入ったときにインスタンス化され、最後のスレッドはコールバックが実行されたときにインスタンス化されます (この場合は EndDoWork)。それは正しいですか、それとも電話で何か間違ったことをしていますか? 同期コンテキストを使用する必要がありますか? 注: メイン スレッドでは、同期コンテキストは null です。
コールバック関数など、スレッド間で情報を「共有」するとどうなりますか? それはパフォーマンスの問題を引き起こしますか、それとも匿名メソッドはデータを共有できるクロージャーのようなものですか?
Framework 4.5 および Async と Await を使用
Framework 4.5 では、コードが以前より単純すぎるように見えます。
public async Task<int> DoWorkAsync(int count)
{
var proxyOne = new Backend.ServiceOne.ServiceOneClient();
var proxyTwo = new Backend.ServiceTwo.ServiceTwoClient();
var doWorkOne = proxyOne.DoWorkAsync(count);
var doWorkTwo = proxyTwo.DoWorkAsync(count);
var result = await Task.WhenAll(doWorkOne, doWorkTwo);
return doWorkOne.Result + doWorkTwo.Result;
}
しかし、この場合、アプリケーションをデバッグすると、コードが同じスレッドで実行されることが常にわかります。ここでの私の質問は次のとおりです。
3.. 「待機可能な」コードを待っているとき、そのスレッドは解放され、スレッド プールに戻ってさらに要求を実行しますか?
3.1. もしそうなら、await タスクから結果を取得すると、実行は前の呼び出しと同じスレッドで完了すると思います。それは可能ですか?そのスレッドが別のリクエストを処理している場合はどうなりますか?
3.2 そうでない場合、スレッドを解放して Asycn および Await パターンでスレッド プールに戻すにはどうすればよいですか?
ありがとうございました!