2010-03-01 2 views
16

.NET 응용 프로그램에서 x 개의 스레드를 시작하고 싶습니다. 수동으로 종료해야 할 때이를 추적하고 싶습니다. 내 신청서는 나중에 내 신청서를 마감합니다.여러 스레드 시작 및 내 .NET 응용 프로그램에서 추적 유지

예 ==> .. 내가 스레드 베타를 종료 말할 수있을 것입니다 내 응용 프로그램의 모든 지점에서 다음 .. 스레드 베타를 시작, 스레드 알파를 시작

열 스레드를 추적하는 가장 좋은 방법은 무엇입니까

.NET에서 무엇을 알아야합니까? (id?) 스레드를 종료하려면 무엇을해야합니까? 샘플 코드, 자습서가 도움이 될 것입니다.

답변

14

나귀 작업을 저장하지 않고 Smart Thread Pool을 사용할 수 있습니다. 이것은 각 스레드의 상태를 언제든지 조회하고 종료 할 수있는 작업 단위 (UOW) 시스템을 제공합니다.

너무 귀찮다면, 언급 한 바와 같이 IDictionary<string,Thread>이 아마도 가장 간단한 해결책 일 것입니다.

public class MyThreadPool 
{ 
    private IList<Thread> _threads; 
    private readonly int MAX_THREADS = 25; 

    public MyThreadPool() 
    { 
     _threads = new List<Thread>(); 
    } 

    public void LaunchThreads() 
    { 
     for (int i = 0; i < MAX_THREADS;i++) 
     { 
      Thread thread = new Thread(ThreadEntry); 
      thread.IsBackground = true; 
      thread.Name = string.Format("MyThread{0}",i); 

      _threads.Add(thread); 
      thread.Start(); 
     } 
    } 

    public void KillThread(int index) 
    { 
     string id = string.Format("MyThread{0}",index); 
     foreach (Thread thread in _threads) 
     { 
      if (thread.Name == id) 
       thread.Abort(); 
     } 
    } 

    void ThreadEntry() 
    { 

    } 
} 

당신은 물론 훨씬 더 복잡하고 그것으로 복잡 할 수 있습니다 심지어 간단한 스레드의 이름을 각각 제공 및 IList<Thread> 사용합니다. 스레드를 죽이는 것이 시간에 민감하지 않은 경우 (예를 들어 UI에서 3 초 내에 스레드를 죽일 필요가없는 경우) Thread.Join()을 사용하는 것이 좋습니다.

아직 읽지 않았다면 Jon Skeet은 "abort use abort"조언에 대해 this good discussion and solution을 가지고 있습니다.

+0

Void ThreadEntry()에서 스레드 시작점의 주 응용 프로그램에서 스레드를 여러 번 만들고 나면 질문을했습니다. 할당 된 스레드 수에 따라 해당 스레드의 다른 응용 프로그램. – shawn

1

얼마나 정교해야하는지에 따라 다릅니다. 도우미 메서드 등으로 ThreadPool의 고유 한 유형을 구현할 수 있습니다. 그러나 목록/배열을 유지하고 그에 따라 컬렉션에 스레드를 추가/제거하는 것만 큼 간단하다고 생각합니다.

사전 컬렉션을 사용하여 고유 한 유형의 특정 키를 사용하여 지침/문자열을 검색 할 수도 있습니다.

2

스레드를 만든 후에는 Name 속성을 설정할 수 있습니다. 그것은 당신이 어떤 컬렉션을 저장한다고 가정하면 검색 (및 중단)하기 위해 LINQ를 통해 편리하게 액세스 할 수 있습니다

var myThread = (select thread from threads where thread.Name equals "myThread").FirstOrDefault(); 
if(myThread != null) 
    myThread.Abort(); 
1

와우, 이렇게 많은 답변이 있습니다 .. 당신은 간단하게 사용할 수 있습니다

  1. 을 스레드를 보유 할 배열로, 배열에 대한 액세스가 복잡 할 경우에만 작동하지만이 배열에 다른 스레드가 액세스하는 경우 액세스를 동기화해야합니다.
  2. 스레드 풀을 사용할 수 있지만 스레드 풀은 매우 제한되어 있으며 고정 된 양의 스레드 만 보유 할 수 있습니다.
  3. 위에서 언급했듯이 안전한 컬렉션을 도입하면 .NET v4에서 훨씬 쉽게 사용할 수있는 자체 스레드 풀을 만들 수 있습니다.
  4. 당신은 뮤텍스 객체의리스트를 유지함으로써 이들을 관리 할 수 ​​있습니다. 뮤텍스 객체는 그 스레드가 언제 완료되어야 하는지를 결정합니다. 스레드는 뮤텍스를 실행하기 전에 실행될 때마다 뮤텍스를 쿼리하고, 설정이 끝나면 뮤트를 관리 할 수 ​​있습니다 어디서나, 그리고 mutex 이후 defenition thread - safe, 그 꽤 쉽게 ..

나는 다른 10 가지 방법을 생각할 수 있지만 작동하는 것 같습니다. 그들이 당신의 필요에 어울리지 않는다면 알려주세요.

3

당신은 스레드의 사전을 작성하고 같은 아이디의 할당 할 수 있습니다 :

Dictionary<string, Thread> threads = new Dictionary<string, Thread>(); 
for(int i = 0 ;i < numOfThreads;i++) 
{ 
    Thread thread = new Thread(new ThreadStart(MethodToExe)); 
    thread.Name = threadName; //Any name you want to assign 
    thread.Start(); //If you wish to start them straight away and call MethodToExe 
    threads.Add(id, thread); 
} 

당신은 죽일를 열거하면 나중에 목록을 사용할 수있는 ID를 기준으로 스레드를 저장하지 않으려면 스레드.

끝내고 싶을 때 중단 할 수 있습니다. 해당 메서드가 스레드를 정상적으로 종료 할 수 있도록 허용하는 일부 조건을 MethodToExe에 추가하는 것이 좋습니다. 예 :

void MethodToExe() 
{ 
    while(_isRunning) 
    { 
     //you code here// 
     if(!_isRunning) 
     { 
      break; 
     } 
     //you code here// 
    } 
} 

사전을 열거하고 Thread.Abort()을 호출 할 수 있습니다.제가 비슷한 질문과 좋은 답변을 잔뜩받은 ThreadAbortException

+0

@ cornerback84 Thread.Abort()를 사용하지 말라고 조언합니다. 스레드를 백그라운드로 설정하는 것이 좋습니다. – Kiril

+0

네,하지만 그 방법을 보여주고 있었을뿐입니다. 그래서 나는 그가 스레드를 중단 할 수있는 조건을 제안했습니다. 그것은 또는 SocketException과 같은 어떤 예외가 methdo를 종료 할 수 있습니다 – ata

3

잡을 준비 수 : Shutting down a multithreaded application

참고 : 제 질문은 우아한 종료를 필요로하지 않았지만, 사람들은 여전히의 루프에서 내가 정상적으로 종료하는 것이 좋습니다 각 스레드.

Thread thread = new Thread(new ThreadStart(testObject.RunLoop)); 
thread.IsBackground = true; 
thread.start(); 

선호되는 방법은 시작에 스레드를 관리 :

기억해야 할 중요한 것은 당신이하지 않으려 경우 스레드가 당신이 배경에 모든 스레드를 설정해야합니다 종료에서 프로세스를 방지한다는 것입니다 ThreadPool이지만, 거기에있는 모든 컨테이너를 사용하여 스레드에 대한 참조를 유지할 수 있습니다. 스레드에는 항상 종료를 알리는 플래그가 있어야하며 계속해서 플래그를 확인해야합니다.

더 나은 제어를 위해 스레드에 CountdownLatch을 제공 할 수 있습니다. 스레드가 루프를 빠져 나올 때마다 CountdownLatch에 신호를 보냅니다. 주 스레드는 CountdownLatch.Wait() 메서드를 호출하고 모든 스레드가 신호를 보낼 때까지 차단됩니다. 이렇게하면 정리를 시작한 후 모든 스레드가 종료되도록 할 수 있습니다.

public class CountdownLatch 
{ 
    private int m_remain; 
    private EventWaitHandle m_event; 

    public CountdownLatch(int count) 
    { 
     Reset(count); 
    } 

    public void Reset(int count) 
    { 
     if (count < 0) 
      throw new ArgumentOutOfRangeException(); 
     m_remain = count; 
     m_event = new ManualResetEvent(false); 
     if (m_remain == 0) 
     { 
      m_event.Set(); 
     } 
    } 

    public void Signal() 
    { 
     // The last thread to signal also sets the event. 
     if (Interlocked.Decrement(ref m_remain) == 0) 
      m_event.Set(); 
    } 

    public void Wait() 
    { 
     m_event.WaitOne(); 
    } 
} 

그것은 Thread.Abort() 메소드가 이상한 일을 언급하는 것이 가치가있다 :

스레드 호출 자체에 중단하는 경우, 효과가 예외를 던지는 유사하다; ThreadAbortException 가 즉시 발생하고 결과는 예측 가능합니다. 그러나 하나의 스레드 이 다른 스레드에서 Abort를 호출하면 코드가 실행 되더라도 중단은 중단됩니다. 정적 생성자가 중단 될 수있는 가능성도 있습니다. 드문 경우이지만 이로 인해 해당 클래스의 인스턴스가 해당 응용 프로그램 도메인에 생성 된 이되지 않을 수 있습니다. 에서 .NET Framework 버전 1.0 및 1.1에서는 finally 블록이 실행 중일 때 스레드가 중단 될 수있는 기회가 있습니다.이 경우 마지막으로 블록이 중단됩니다. 호출

스레드 중단 수도 이 중단되고있는 스레드가 같은 catch 블록, 마지막으로 블록 또는 제약 실행 영역으로 코드의 보호 지역에있는 경우 블록. Abort를 호출하는 스레드가 이라면 중단 된 스레드 에 필요한 잠금이 유지되면 교착 상태가 발생할 수 있습니다.

1

각 스레드를 시작할 때 해당 스레드를 ManagedThreadId를 키로, 스레드 인스턴스를 값으로 넣습니다. 각 스레드의 콜백을 사용하여 ManagedThreadId를 반환합니다.이 스레드를 사용하면 사전이 종료 될 때 사전에서 스레드를 제거 할 수 있습니다. 필요할 경우 사전을 걸어 스레드를 중단 할 수도 있습니다. 앱이 예기치 않게 종료되면 종료되도록 스레드 백그라운드 스레드를 만듭니다.

별도의 콜백을 사용하여 UI가 설정 한 플래그를 반영하는 스레드에 신호를 보내 계속 진행하거나 중단 할 수 있습니다. 스레드를 중단해야하는 경우 정리 작업을 수행 할 수 있도록 스레드에 ThreadAbortException을 잡아 두어야합니다.

관련 문제