2010-12-03 4 views
1

Startメソッドでは、長期実行タスクを別のスレッドに委譲する次のプログラムがあります。 Stopメソッドが呼び出されると、私はワーカースレッドが現在のタスクの実行を完了し、途中に残さないようにする必要があります。タスクが既に完了してスリープ状態にある場合、即座に停止することができます。タスクが非同期スレッドによって処理されるまで、メインスレッドが停止するまで待ちます。

どうすればいいですか教えてください。あなたは常に終了する全体として、実行時間の長いタスクスレッドをしたいスレッドがThread.Join()を呼び出して実行されるまで、あなたは待つだけしたと仮定すると

static int itemsProcessed = 0; 
    static Thread worker; 
    static void Start() 
    { 
     var ts = new ThreadStart(Run); 
     worker = new Thread(ts); 
     worker.Start(); 
    } 

    static void Stop() 
    { 
     //wait until the 'worker' completes processing the current item. 
     Console.WriteLine("{0} Items Processed", itemsProcessed); 
    } 

    static void Run(object state) 
    { 
     while (true) 
     { 
      ALongRunningTask(); 
      itemsProcessed++; 
      Thread.Sleep(1000); 
     } 
    } 

答えて

1

1つの方法は、2つのスレッドbetweej通信する揮発性の変数を使用することです。これを行うには、 "volatile bool isRunning;"を作成します。 Startで値をtrueに設定し、次にwhileループを "while(isRunning)"に実行します。 stopでは、isRunningをfalseに設定してからworker.Join()を呼び出します。これにより、現在のアイテムの処理が終了するとrunメソッドが終了し、スレッドが終了するまでJoinが待機します。

最後に行う必要があるのは、スレッドセーフな方法でitemsProcessedにアクセスすることです。現在のコードでは、Stopが別のスレッドから変更されているのでitemsProcessedの最新の値を見るかどうかを知る方法がありません。 1つのオプションはitemsProcessedのロックを作成し、Runの内部でロックを保持し、StopのWriteLineステートメントの前にロックを取得することです。

1

あなたのスレッドで正常に作業を完了したい場合は、何らかのメッセージを渡す必要があります。最も単純なケースでは、ブール値になる可能性があります。あなたのケースでは、スレッドが1つしかないようですこれを行うには、静的変数(ここでは可能な限り簡素化)

static volatile bool processing = true; 
static void Stop() 
{ 
    processing = false; 
    //wait until the 'worker' completes processing the current item. 
    worker.Join(); 
    Console.WriteLine("{0} Items Processed", itemsProcessed); 
} 


static void Run(object state) 
{ 
    while (proccessing) 
    { 
     ALongRunningTask(); 
     itemsProcessed++; 
    } 
} 
+0

これは処理が揮発性である必要があります。そうしないと、他のスレッドは値が変更されたことを決して知らないことがあります。また、スリープループの代わりにworker.Joinメソッドを使用することもできます。 –

+0

両方の正しいステートメント、私はちょっとした試作をしています。投稿を編集しました – BrokenGlass

関連する問題