.NET Webサービス& BackgroundWorkerスレッド
-
04-07-2019 - |
質問
Webサービスメソッドで非同期処理を実行しようとしています。次のAPI呼び出しがあるとしましょう: http://www.example.com/api.asmx
そしてメソッドは GetProducts()と呼ばれます。
このGetProductsメソッドは、何かを行う(たとえば、データベースからデータを取得する)後、結果を返す直前に、非同期を行う(たとえば、メールを送信する)
これが私がやったことです。
[WebMethod(Description = "Bal blah blah.")]
public IList<Product> GetProducts()
{
// Blah blah blah ..
// Get data from DB .. hi DB!
// var myData = .......
// Moar clbuttic blahs :) (yes, google for clbuttic if you don't know what that is)
// Ok .. now send me an email for no particular reason, but to prove that async stuff works.
var myObject = new MyObject();
myObject.SendDataAsync();
// Ok, now return the result.
return myData;
}
}
public class TrackingCode
{
public void SendDataAsync()
{
var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += BackgroundWorker_DoWork;
backgroundWorker.RunWorkerAsync();
//System.Threading.Thread.Sleep(1000 * 20);
}
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
SendEmail();
}
}
今、このコードを実行すると、メールは送信されません。 Thread.Sleep ..のコメントを外すと、電子メールが送信されます。
では...なぜバックグラウンドワーカースレッドが破棄されるのですか?親スレッドに依存していますか?これは、asp.net Webアプリでバックグラウンドまたはフォークスレッドを行うべき間違った方法ですか?
解決
BackgroundWorker
は、たとえば親和性の理由で、UI *スレッドに同期して戻す必要がある場合に役立ちます。この場合、単に ThreadPool
を使用するだけで十分である(そしてより単純になる)と思われます。ボリュームが大きい場合、プロデューサー/コンシューマーキューを使用すると、より適切な調整が可能になる場合があります(したがって、スレッドにdrれません)。
public void SendDataAsync()
{
ThreadPool.QueueUserWorkItem(delegate
{
SendEmail();
});
}
また-寝ることで何を達成したいのかよくわかりませんか?これはスレッドを結び付けるだけです(CPUは使用しませんが、どちらもうまくいきません)。手入れをしますか?実際のWebページを一時停止しているように見えます(つまり、スリープは電子メールスレッドではなく、Webページスレッドで発生します)。ここで何をしようとしていますか?
* =実際には、同期コンテキストが設定されているものを使用します
他のヒント
再生産者/消費者。基本的には、何らかの種類のスロットルを維持するだけの価値があります。最も単純なレベルでは、 Semaphore
を(通常の ThreadPool
と一緒に)使用して、既知の量の作業に制限することができます(スレッドプールの飽和を回避するため)。しかし、生産者/消費者キューはおそらくより効率的で管理されます。
Jon Skeetにはこのようなキューがありますこちら( CustomThreadPool コード>)。あなたが望むなら、おそらくそれについていくつかのメモを書くことができます。
つまり、外部のWebサイトを呼び出している場合、ネットワークIO /完了ポートで多くの待機が発生する可能性が非常に高くなります。そのため、スレッドの数をわずかに増やすことができます...明らかに(対照的に)作業がCPUにバインドされている場合、CPUコアよりも多くのスレッドを持つことは意味がありません。
20秒後に、BackgroundWorkerインスタンスが参照を持たない(スコープ外になった)ためにガベージコレクションされる可能性があるため、破棄される可能性があります。