14

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 アプリでバックグラウンドまたは分岐スレッドを行うべき間違った方法ですか?

4

3 に答える 3

18

BackgroundWorkerアフィニティの理由などで (たとえば) UI* スレッドに同期する必要がある場合に便利です。この場合、単に を使用ThreadPoolするだけで十分 (そしてはるかに簡単) になるように思われます。ボリュームが大きい場合は、プロデューサー/コンシューマー キューを使用するとスロットリングが改善される可能性があります (スレッドに溺れないようにするため) - しかし、ThreadPoolここでは問題ないと思います...

public void SendDataAsync()
{
    ThreadPool.QueueUserWorkItem(delegate
    {
        SendEmail();
    });
}

また、睡眠によって何を達成したいのかよくわかりませんか?これはスレッドを拘束するだけです(CPUを使用していませんが、どちらも役に立ちません)。詳しく説明しますか?実際の Web ページを一時停止しているようです (つまり、スリープは電子メール スレッドではなく、Web ページ スレッドで発生します) ここで何をしようとしていますか?

*=実際には、同期コンテキストが設定されているものは何でも使用します

于 2008-10-23T07:08:48.970 に答える
1

再生産者/消費者; 基本的に、ある種のスロットルを維持するだけの価値があります。最も単純なレベルでは、 aSemaphoreを (通常の とともにThreadPool) 使用して、既知の量の作業に制限することができます (スレッド プールが飽和状態になるのを避けるため)。ただし、生産者/消費者キューはおそらくより効率的で管理されます。

Jon Skeet はここにそのようなキューを持っています( CustomThreadPool)。必要に応じて、おそらくそれについてのメモを書くことができます。

とはいえ、外部の Web サイトを呼び出している場合は、ネットワーク IO/完了ポートで多くの待機が発生する可能性が非常に高くなります。そのため、わずかに多くのスレッドを使用できます...明らかに (対照的に) 作業が CPU バウンドの場合、CPU コアよりも多くのスレッドを使用しても意味がありません。

于 2008-10-27T23:28:20.653 に答える
0

20 秒後、その BackgroundWorker インスタンスは参照がない (スコープ外になった) ためにガベージ コレクションされる可能性があるため、取り壊される可能性があります。

于 2008-10-23T07:20:03.737 に答える