0

sを使用することによるスレッド セーフの意味を理解するのに苦労していますRunWorkerCompletedHandler。私はスタックオーバーフローの他の場所でこれを見つけました:

UI スレッドで BackgroundWorker が作成された場合、DoWork はスレッド プール スレッドで実行され、RunWorkerCompleted は UI スレッドで実行されます。

BackgroundWorker がバックグラウンド スレッド (つまり、UI スレッドではない) で作成された場合、DoWork は引き続きスレッド プール スレッドで実行され、RunWorkerCompleted もスレッド プール スレッドで実行されます。

次のクラスがあるとします。

class TestingClass
{
    private BackgroundWorker _bgWorker = new BackgroundWorker();
    private int _counter = 0;

    private readonly int _creatorID;

    public TestingClass()
    {
        _creatorID = Environment.CurrentManagedThreadId;

        _bgWorker.DoWork += DoAsyncWork;
        _bgWorker.RunWorkerCompleted += CompleteAsyncWork;
        _bgWorker.RunWorkerAsync();
    }

    public void IncrementCounter()
    {
        // We only allow the creator of this instance to call this function
        // because instances of this class will not be shared with other threads.
        Debug.Assert(_creatorID == Environment.CurrentManagedThreadId);

        ++_counter;
    }

    private void DoAsyncWork(object sender, DoWorkEventArgs e)
    {
        int i = 0;
        while (i < 100000)
            ++i;
    }

    private void CompleteAsyncWork(object sender, RunWorkerCompletedEventArgs e)
    {
        // Apparently _creatorID == Environment.CurrentManagedThreadId isn't guaranteed here!

        // Modification of member variable after the asynchronous part
        // has been completed.
        ++_counter;
    }
}

CompleteAsyncWorkインスタンスを作成したスレッドで必ずしも実行されるとは限らないため、実行中に作成スレッドが呼び出される可能性があると想定していIncrementCounterますCompleteAsyncWorkRunWorkerCompletedHandlerこの場合、メンバ変数を変更しても安全ですか? いいえの場合、正しいアプローチは何でしょうか?

4

1 に答える 1