2017-12-01 5 views
0

2つのスレッドを使って数値を数える小さなプログラムを作った。それはまた、カウントの隣に2番目の数字を表示するので、どのスレッドがどの番号を表示しているかを見ることができます。すぐにすべてのスレッドを殺す方法

私の目標は、それらのうちの1つが7とカウントされるとすぐに両方のスレッドを停止させることです。私はそれについてどうなるかわかりません。私はCounterへのパラメータとしてスレッド配列を渡すことを考え、両方のスレッドを中止するためにforeachループを使用します。問題はt0がそれを実行している可能性があり、t0.Abort()を呼び出すため、t1.Abort()はもう呼び出されないということです。

public static int count = 0; 
private static object lockObject = new object(); 

static void Main(string[] args) { 
    Thread t0 = new Thread(() => Counter(1, 10)); 
    Thread t1 = new Thread(() => Counter(10, 20)); 

    t0.Start(); 
    t1.Start(); 

    t0.Join(); 
    t1.Join(); 

    Console.ReadLine(); 
} 

public static void Counter(int k, int m) { 
    for(int i = k; i < m; i++) { 
     lock (lockObject) { 
      count++; 
      Console.WriteLine(count + " " + i); 
      if (i == 7) { 
       /* 
       * Code that will kill thread t0 and t1 
       */ 
      } 
     } 
    } 
} 

出力は

1 1 
2 2 
3 10 
4 11 
5 12 
6 13 
7 14 

ような何か誰かがt0t1の両方を殺すためにどのような提案を持っていなければなりませんか?

+0

プレーンスレッドの代わりに 'タスク'を使用してもよろしいですか?もしそうなら、最初のスレッドがメインスレッドで終了するまで待つ簡単な方法があります。そして、それらをすべて終了することができます。 –

+0

あなたの目標はどちらのスレッドも14以上の数字を印刷しないようにすることです。そして、カウントは決して減少しませんよね?なぜ、各スレッドがcount> 14を見たときに_itself_(すなわち、リターン)を殺すのではないのですか? –

+0

'CancellationTokenSource'はあなたの友人です。 – code4life

答えて

3

フラグ(この場合は「実行」)を使用します。

public static int count = 0; 
private static object lockObject = new object(); 
static bool run = true; 

static void Main(string[] args) { 
    Thread t0 = new Thread(() => Counter(1, 10)); 
    Thread t1 = new Thread(() => Counter(10, 20));   

    t0.Start(); 
    t1.Start(); 

    t0.Join(); 
    t1.Join(); 

    Console.ReadLine(); 
} 

public static void Counter(int k, int m) { 
    for(int i = k; i < m && run; i++) { 
     lock (lockObject) { 
      count++; 
      Console.WriteLine(count + " " + i); 
      if (i == 7) { 
       run = false; 
      } 
     } 
    } 
} 
+0

私が読んだことから、常にvolatileを使うのは本当に悪いですか? – Robbebeest

+0

@エヴァーク完了、それは揮発性なしで動作するはずです。 - ) – epinal

+1

@Robbebeest正しく使用するのは非常に難しく、その使い方については非常に精通していなければなりません。そうでなければ、 'volatile'を使うのではなく、' lock'のような適切な同期を代わりに使うべきです。 – Servy

2

ManualResetEventをご覧ください。 1つを作成し、Counter-methodのfor-loopの内部でイベントが設定されているかどうかを確認し、そうであればfor-loopを解除して戻ります。 7に達したら、単にイベントを設定します。このイベントはスレッドセーフです。

ところで、大学の宿題のようですが、次回は自分で試してみてください。

public static int count = 0; 
private static object lockObject = new object(); 
private ManualResetEvent finish = new ManualResetEvent(false); 

static void Main(string[] args) { 
    Thread t0 = new Thread(() => Counter(1, 10)); 
    Thread t1 = new Thread(() => Counter(10, 20)); 

    t0.Start(); 
    t1.Start(); 

    t0.Join(); 
    t1.Join(); 

    Console.ReadLine(); 
} 

public static void Counter(int k, int m) { 
    for(int i = k; i < m; i++) { 

     lock (lockObject) { 
      if (finish.waitOne(0)) 
       break; 

      count++; 
      Console.WriteLine(count + " " + i); 
      if (i == 7) 
       finish.set() 
     } 
    } 
} 
+0

まだ7歳を数えます。私はもう少し自分で試しましたが、何を検索するか分からないこともあります。たとえば、ManualResetEventについて聞いたことがありませんでした。しかし、ええ、それは大きな運動の小さな部分です;) – Robbebeest

+0

ああ、lockObjectの直後にif(finish.isset())を移動してください。 1つのスレッドがlockObjectを待っていて、イベントをもう見ていないため(イベントがロックの前にあるため)、過去7回もカウントされます。私はコードを更新しました。 – Matthias

+0

また、lockObjectの代わりにセマフォまたは同期化のevent.waitOneメソッドを使用することもできます。 – Matthias

0

MSDN ManualResetEvent.isset()は何か分かりませんが、Matthiasの答えは正しいように見えます。 isset()WaitOne(0)を置き換えると、コードは正常に動作します。

private static int count = 0; 
private static ManualResetEvent finish = new ManualResetEvent(false); 
private static int stopValue = 7; 
private static int syncInterval = 0; //0ms 
private static object lockObject = new object(); 
static void Main(string[] args) 
{ 
    Thread t0 = new Thread(() => Counter(1, 10)); 
    Thread t1 = new Thread(() => Counter(10, 20)); 
    t0.Name = "Thread 1"; 
    t1.Name = "Thread 2"; 

    t0.Start(); 
    t1.Start(); 

    t0.Join(); 
    t1.Join(); 

    Console.ReadKey(); 
} 
public static void Counter(int k, int m) 
{ 
    for (int i = k; i < m; i++) 
    { 
     lock (lockObject) 
     { 
      if (finish.WaitOne(syncInterval)) 
       break; 
      count++; 
      Console.WriteLine($"{count} {i}"); 
      if (count == stopValue) 
      { 
       finish.Set(); 
      } 
     } 
    } 
} 
+0

あなたはそうです。私はもはやC#で作業していないし、ビジュアルスタジオをインストールしていない。だからコードはちょうど私の脳の外だった – Matthias

関連する問題