2017-12-01 2 views
0

두 개의 스레드를 사용하여 숫자를 계산하는 작은 예제 프로그램을 만들었습니다. 또한 숫자 옆에 두 번째 숫자를 인쇄하므로 어느 번호의 스레드가 인쇄되었는지 확인할 수 있습니다.모든 스레드를 즉시 죽이는 방법

이제 내 목표는 두 스레드 중 하나가 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

내가 읽은 바로는 항상 휘발성 메모리를 사용하는 것이 정말 안좋은가요? – Robbebeest

+0

@Evk 완료, 휘발성없이 작동합니다. -) – epinal

+1

@Robbebeest 올바르게 사용하기가 어렵고, 어떻게 사용하고 정확하게 사용하는지에 대해 매우 잘 알고 있어야합니다. 그렇지 않다면'휘발성 '을 사용하는 대신 여기에서했던 것처럼'잠금 '과 같은 적절한 동기화를 사용해야합니다. – Servy

2

ManualResetEvent를 살펴보십시오. 하나를 만들고 카운터 메소드의 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())를 이동하십시오. 하나의 쓰레드가 lockObject를 기다리고있어 이벤트를 더 이상 보지 않아서 (이벤트가 잠금 이전이기 때문에) 여전히 7을 계산합니다. 코드를 업데이트했습니다. – Matthias

+0

lockObject 대신 synchonization을 위해 세마포 또는 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

관련 문제