2

2つのスレッドがあるとします。1つのスレッドで、一連のジョブを実行しています。もう一方のスレッドでは、ユーザー入力がそれらのジョブを制御するのを待っています(つまり、次のジョブにスキップします)。例(疑似C#):

public class Worker {

    public List<Job> Jobs { get; set; }

    public Worker(Controller anotherThread) {
        anotherThread.SkipJobRequested += OnSkipJobRequested;
    }

    public DoWork() {
        foreach (Job job in Jobs) {
            // Do various work...
        }
    }

    // Event that fires on Controller thread
    public void OnSkipJobRequsted(Object sender, EventArgs args) {
        // Somehow skip to the next job
    }
}

次の仕事へのスキップをどのように処理すればよいかわかりません。私が思い浮かぶ可能性の1つはIsSkipRequested、スキップが要求されたときに設定したインスタンス変数(、など)を持ち、内のさまざまな時点でそれをチェックすることDoWork()です。

このイベントを処理するために使用できる他のパターンはありますか?

4

2 に答える 2

3

もう 1 つのパターンは .Net クラスのBackgroundWorkerです。これは、目的に適しているようです。JobをBackgroundWorkerのサブクラスにして、循環させることができます。違いは、BackgroundWorkerは UI スレッドを認識せず、キャンセルが要求されたかどうかのみを認識することです。

このパターンでは、UI スレッドがCancelAsyncを呼び出し、次にDoWorkメソッドが都合のよい間隔でCancellationPendingをチェックして、続行するかどうかを決定します。RunWorkerCompletedイベント ハンドラー内で、次のジョブに対してRunWorkerAsyncを呼び出します。

于 2012-08-03T00:14:25.353 に答える
1

もう 1 つの提案は (上記で述べたように) を作成List<Jobs>Queue<Jobs>、オブジェクトで現在実行中のジョブを維持する foreach を実行する DoWork ではなく、処理の準備ができたら各アイテムを単純にデキューすることです。

タスク並列ライブラリを使用すると、キャンセル トークンを指定できます (ただし、おそらくこれをジョブ実行コードに渡して、そこでキャンセルを処理する必要があります)。スキップが押されたときに RequestCancellation を呼び出して、次のジョブを開始できます。待ち行列。さらに、新しいタスクを開始するときに、完了時に実行するアクションを指定できます。これにより、タスクを一連の順序にまとめて、必要に応じてタスクをスキップできます。以下は、キャンセル トークンのない例です。

        _currentJob = Jobs.DeQueue();
        Task.Factory.StartNew(() => {_currentJob.execute();}, 
        () => 
        {
            //On task completion logic
            ExecuteNextJobFromQueue();                              
        }

ジョブの実行中にキャンセルを確認する必要があるため、ジョブが 1 つの大きなブロック タスクではなく複数のタスクを実行している場合、このアプローチがおそらく最適に機能することに注意してください。

于 2012-08-04T09:14:25.537 に答える