2

ThreadPool.QueueUserWorkItem(...)を使用して開始されたバックグラウンドタスクをキャンセルする必要があります。私はBackgroundWorkerが特にこの種のもののための構造を持っていることを知っていますが、ユーザーインターフェースが関与していないので、この場合はやり過ぎだと思います。キャンセルとは、単にコールバックメソッドの完了を強制することを意味します。

次のようなものをクラスに追加することの落とし穴は何ですか?

// Cancellation Property.
private bool _canceled;
public bool CancelTask
{
    get { return _canceled; }
    set { _canceled = value; }
}

public void DoSomeTask()
{
    int iterations = 50;
    ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolCallback), iterations);
}

private void ThreadPoolCallback(object state)
{
    if (_canceled)
        return; // don't even start.

    int iterations = (int)state;
    for (int i = 0; !_canceled && i < iterations; i++)
    {
        //
        // do work ...
        //

        // This allows you to cancel in the middle of an iteration...
        if (_canceled)
            break;
    }
}

もっと良い方法はありますか?

4

1 に答える 1

3

プロパティではなく、CancelTask​​()メソッドを使用します。重要なのは、発信者はタスクをキャンセルできる必要がありますが、誰もタスクをキャンセルできないようにする必要があるということです。

次に、_cancelledの読み取りと書き込みに適切なメモリバリアがあることを確認する必要があります。そうしないと、一方のスレッドがもう一方のスレッドによって行われた変更を監視できない可能性があります。このために、Thread.VolatileWrite(CancelTask​​内)とThread.VolatileRead(ループ内)を使用します

于 2011-10-11T19:56:29.087 に答える