2010-01-18 3 views
1

다시 Thread.Abort 함수의 안전성에 대해 이야기하고 싶습니다. 나는 정말로 제어 할 수없고 실제로 원하지 않는 작업을 중단하는 방법을 갖고 싶었지만, 가능한 한 빨리 스레드를 제거하여 스레드가 내 응용 프로그램의 목이 마르지 않도록하고 싶습니다..NET Thread.Abort again

그래서 어떤 테스트 코드를 작성하여 Thread.Abort을 사용할 수 있는지보고 중단 스레드가 자원을 효율적으로 정리하도록하십시오. 일부 스레드가 마지막으로 중단되었다 아마 아무 중단 완료 또는 때문에,이 코드는 약 5 분 동안 일했으며, threadRunCountthreadFinally 항상 동일이었다 threadAbort이 수의 다소 낮았다 지금까지

int threadRunCount = 0; 
int threadAbortCount = 0; 
int threadFinallyCount = 0; 
int iterations = 0; 

while(true) 
{ 
Thread t = new Thread(() => 
{ 
    threadRunCount++; 
    try 
    { 
    Thread.Sleep(Random.Next(45, 55)); 
    } 
    catch(ThreadAbortException) 
    { 
    threadAbortCount++; 
    } 
    finally 
    { 
    threadFinallyCount++; 
    } 
}); 

t.Start(); 
Thread.Sleep(45); 
t.Abort(); 

iterations++; 
} 

그래서 : 여기에 코드입니다 .

문제는 무엇인가 놓치겠습니까?

답변

4

인위적인 테스트를 통해 무엇이든 증명할 수 있습니다.

당신이 증명 한 바에 따르면 으로 테스트 코드, Thread.Abort이 제대로 작동하는 것 같습니다.

그러나 처분해야 할 물건을 사용하자마자 모든 희망은 사라집니다. 지금

using (Stream stream = new FileStream(@"C:\Test.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.None)) 
{ 
    Thread.Sleep(Random.Next(45, 55)); 
} 

잠시 동안 실행하고 여전히 작동하는지 말해 :

는 예를 들어,이 코드를 사용해보십시오.

코드가 절전 모드를 종료하고 사용 블록의 암시 적 finally 블록 안에 있고 스트림을 닫으려고하면 문제가 나타납니다.

Thread.Abort의 문제는 예외를 throw하지 않아야하는 코드 내에서도 어디서나이 발생할 수 있다는 것입니다.

는 예를 들어, 당신은 정말 다음 코드은 if 표현을 평가 한 후 충돌 할 것으로 예상, 그러나 전에 Dispose 울어 통해 간? 그것은 바로 .Dispose 호출 후 발생하면 어떻게

if (_ObjectToDispose != null) 
{ 
    _ObjectToDispose.Dispose(); 
    _ObjectToDispose = null; 
} 

? 필드는 여전히 null이 아닌 값을 가지므로 다른 곳에서는 미묘한 문제가 발생할 수 있습니다.당신이 할 경우에는 어떻게

:이 코드

IDisposable objectToDispose = Interlocked.Exchange(ref _ObjectToDispose, null); 
if (objectToDispose != null) 
    objectToDispose.Dispose(); 

을, 당신은 가치를 잡고는, 널 (null)으로 대체하고, 당신이 Dispose를 호출 한 주위에 도착하기 전에 다음, 당신의 ThreadAbortException 그냥 떠날 것이다, 발생 목적.

나를 그냥 포인트 집으로 운전하자

Thread.Abort이 결코가 프로그램을 종료 (또는 스레드에서 실행하는 사용자 정의 응용 프로그램 도메인을 해체 할 필요가 시나리오를 제외하고 사용되어야한다 그것). 결코 Thread.Abort를 호출하고 계속 실행해야합니다.

향후 일정에 버그를 계획하지 않는 한. 이 경우 바로 가서 Thread.Abort을 사용하십시오. 문제가 발생할 것이라는 것을 거의 보장 할 수 있기 때문입니다.

+0

파일 열기를 언급 한 코드를 실행하려고했는데 새 스레드가 생성 된 후 어느 시점에서 예 파일은 여전히 ​​중단되어야하는 다른 스레드와 함께 계속 사용되고 있지만 스레드가 공유 리소스를 사용하지 않으면 어떻게됩니까? 스레드 중단이 다소 안전하지 않다는 것을 증명하는 것 같습니다. 일부 응용 프로그램을 종료해야 할 수도 있지만 일부 관리되지 않는 코드가 실행 중이면 프로세스 중단을 초래하거나 메모리 누수가 발생할 수 있습니까? 제 경우에는 프로세스 실행 시간을 정확한 제한 시간 한도로 제한 할 수있는 것이 필요했고 제 경우에는이 프로세스 실행을 제어 할 수 없었습니다. 이 사건에 대한 아이디어가 있습니까? – hoodoos

+0

SO에 대해 다른 질문을하고, 실행 시간을 제한하는 방법, 그리고 그 코드에서 수행하려는 것을 게시해야합니다. 경우에 따라 코드가 비 관리 코드에서 사용 중이면 원하는 것을 수행 할 수 없습니다 (예 : 이를 수행하는 유일한 "안전한"방법은 제한 시간 경과 후 완전히 종료되는 하위 프로세스를 생성하는 것입니다. –

+2

작은 수정 (비록이 대답이 1 년이 넘었음에도 불구하고) 스레드는 catch와 finally 블록 내에서 취소 할 수 없습니다. 따라서 잘 작성된 finally 블록을 사용하거나 블록을 사용한다고 가정하면 위 예제는 실제로 문제가되지 않습니다. – Steve

-1

Thread.Abort를 사용하는 것이 좋습니다. 그러나, 그것은 항상 즉시 중단되지는 않습니다. 스레드가 관리되지 않는 코드를 수행하는 경우 관리되는 코드로 돌아올 때까지 실제로 중단되지 않습니다.

1

스레드 중단을 사용하면 충분히 안전합니다. 그러나 다른 사람들에 의해 언급 되었 듯이 스레드 중단은 즉시 중단되지 않을 수도 있습니다. thread abort를 호출하면 (자), thread로 ThreadAbortException가 발생합니다. 리소스를 정리하려면이 예외를 catch하고 필요한 정리 작업을 수행 할 수 있습니다.

static void Run() 
{ 
    try 
    { 
    while(someCondition) 
    { 
     .... 
     .... 
     .... 
     if (someOtherCondition) 
      throw new ThreadAbortException("Thread aborted"); 
    } 
    } 
    catch(ThreadAbortException e) 
    { 
    ... 
    ... //clean up resources here. 
    ... 
    } 
    finally 
    { 
    ... 
    } 
} 
+0

스레드에서 정리가 필요한 리소스를 두 번째로 소개하면 Thread.Abort는 충분히 안전하지 않습니다. –

+0

분명히 문제는 Thread.Abort가 코드가 실제로 finally 블록에 있다는 것을 알기에 충분히 똑똑하지 않고 해당 블록에서 바로 중단된다는 것입니다. 코드가 catch/finally에 있지 않고 블록을 빠져 나갈 때까지 기다릴 수만 있다면 알려줄 수 있고 중단 할 수 있습니다 ... – devios1