2009-10-24 14 views
7

私は自分のプロジェクトの一部で非同期メソッドを使用していますが、アプリケーションのスケーラビリティを大幅に向上させることができます。しかし、非同期メソッドが実際にバックグラウンドでどのように機能するのか疑問に思っていますか? .NET(またはWindows?)が通話が完了したことをどのように知っていますか?私が作った非同期呼び出しの数によっては、新しいスレッドが作成されているのがわかります(常にそうとは限りません...)。どうして?非同期メソッドはC#でどのように機能しますか?

さらに、リクエストを完了するまでの時間を監視したいと思います。概念をテストするために、Webサービスを非同期に呼び出し、ストップウォッチを開始した直後に次のコードを記述しました。

for (int i = 0; i < 10000; i++) 
{ 
    myWebService.BeginMyMethod(new MyRequest(), result, new AsyncCallback(callback), i); 
    stopWatches[i].Start(); 
} 
// Call back stop the stopwatch after calling EndMyMethod 

すべての要求(10000)は、同じ時間を開始し、期間は(0 =期間1を呼び出すなど1 =期間2を呼び出す)直線的に上がるだろう持っているので、これは動作しません。非同期メソッド(要求が実際に実行されてから最後まで)を使用して、呼び出しの実際の期間をどのように監視できますか?


UPDATE:非同期メソッドが流れを遮断していますか?私はそれがThreadPoolを使用していることを理解していますが、IAsyncResultは通話が完了したことを知り、CallBackメソッドを呼び出す時間ですか?

+0

1. ThreadPool、2. ThreadPoolの仕組みの詳細を参照してください。しかし、あなたが望むものは一般的な方法では可能ではないと思います。 http://msdn.microsoft.com/en-us/library/ms973903.aspx –

答えて

3

コードは鉄道であり、糸は列車です。列車が鉄道に乗るとき、コードを実行します。

BeginMyMethodは、メインスレッドによって実行されます。 BeginMyMethodの内部を見ると、ThreadPoolのキューに代理人MyMethodが追加されます。実際のMyMethodは列車プールの列車の1つによって実行されます。 MyMethodが完了したときに呼び出される完了ルーチンは、残りのコードを実行するメインスレッドではなく、MyMethodを実行した同じスレッドによって実行されます。スレッドプールスレッドがビジー状態でMyMethodを実行している間、メインスレッドは鉄道システムの他の部分に乗るか(他のコードを実行する)、特定のセマフォが点灯するまで待ってスリープすることができます。

IAsyncResult完了ルーチンを呼び出すタイミングを「知っています」というようなことはありません。完了ルーチンは、単にスレッドプールのスレッドによって呼び出された代理人です。MyMethodの実行が終了した直後です。

私はあなたに多少幼稚な列車の類推に気をつけないことを願っています。人にマルチスレッドを説明するとき、それが何度も助けられました。

+0

私は列車の類推が好きです!ありがとう! :) – Martin

1

要点は、Beginを呼び出すと、メソッドの実行要求がキューに入れられることです。このメソッドは実際にはランタイムによって提供されるワーカースレッドのセットであるThreadPoolで実行されます。

スレッドプールは、非同期タスクがキューに入れられるときに突然処理する固定されたスレッドセットです。これは、実行時間が長くて長くかかるのがなぜ分かるのかを説明します。メソッドはそれぞれほぼ同じ時間に実行されますが、キュー内の以前のすべてのメソッドが実行されるまで開始されません。

実際に非同期メソッドを実行するのにかかる時間を監視するには、メソッドの開始時と終了時にタイマーを開始および停止する必要があります。

ここにはThreadPoolクラスのドキュメントと、進行中の状況を説明するためのより良い仕事をしているasync methodsに関する記事があります。

1

非同期メソッドは、.NET ThreadPoolを使用して動作します。彼らはバックグラウンドで作業するために、作業をThreadPoolスレッドにプッシュします(潜在的に1つを作成しますが、通常は1つを再利用するだけです)。

あなたが行っていることを行うことはできますが、ThreadPoolには動作するスレッドの数が限られています。あなたはあなたの仕事をバックグラウンドスレッドに振りかざすつもりです。最初のものはすぐに実行されますが、しばらくするとキューに入れられ、 "タスク"が完全に実行されるまで動作しません。これにより、スレッドの外観がより長く長くなります。

ただし、ストップウォッチの基準には多少の欠陥があります。 1つのタスクを完了するためにN回ではなく、N回のタスクを完了するのにかかる合計時間を測定する必要があります。これははるかに有用なメトリックになります。

0

実行時間の大部分がBeginMyMethod()より前に発生する可能性があります。その場合、測定値が低すぎます。実際には、APIに応じて、BeginMyMethod()がスタックを離れる前にコールバックを呼び出すことがあります。 StopWatch.Start()へのコールを上げると、それは役に立ちます。

関連する問題