2010-03-26 4 views
3

다른 종류의 작업을 수행하기 위해 다른 스레드를 실행하는 Windows Forms 응용 프로그램이 있습니다. 때때로 모든 스레드 (UI 스레드 포함)가 멈추고 내 앱이 응답하지 않게됩니다. GC가 모두 관리 스레드를 일시적으로 고정하므로 가비지 수집기 관련 문제 일 수 있다고 판단되었습니다. 그 단지 관리 스레드 내가 타임 스탬프와 "하트 비트"파일에 모든 초를 기록 관리되지 않는 하나를 스핀 업, 냉동, 그것이 영향을받지 않습니다 확인하려면 (즉, 여전히 실행) :이 응용 프로그램이 멈추는 시나리오를 어떻게 시뮬레이트 할 수 있습니까?

public delegate void ThreadProc(); 

[DllImport("UnmanagedTest.dll", EntryPoint = "MyUnmanagedFunction")] 
public static extern void MyUnmanagedFunction(); 

[DllImport("kernel32")] 
public static extern IntPtr CreateThread(
    IntPtr lpThreadAttributes, 
    uint dwStackSize, 
    IntPtr lpStartAddress, 
    IntPtr lpParameter, 
    uint dwCreationFlags, 
    out uint dwThreadId);  

uint threadId; 
ThreadProc proc = new ThreadProc(MyUnmanagedFunction); 
IntPtr functionPointer = Marshal.GetFunctionPointerForDelegate(proc); 
IntPtr threadHandle = CreateThread(IntPtr.Zero, 0, functionPointer, IntPtr.Zero, 0, out threadId); 

내 질문 어떻게 관리 스레드가 일시 중지되었지만 관리되지 않는 스레드가 계속 회전하고있는 상황을 시뮬레이트 할 수 있습니까?

내 첫 자상 : 사전에

private void button1_Click(object sender, EventArgs e) { 
    Thread t = new Thread(new ThreadStart(delegate { 
     new Hanger(); 
     GC.Collect(2, GCCollectionMode.Forced); 
    })); 
    t.Start(); 
} 
class Hanger{ 
    private int[] m_Integers = new int[10000000]; 
    public Hanger() { } 
    ~Hanger() { Console.WriteLine("About to hang..."); 

    //This doesn't reproduce the desired behavior 
    //while (true) ; 

    //Neither does this 
    //Thread.Sleep(System.Threading.Timeout.Infinite); 
    } 
} 

감사합니다!

+0

동결이란 영구적으로 반응이 없거나 응답이없는 기간입니까? 몇 개의 스레드 및 어떤 종류의 잠금 및/또는 동기화 메커니즘을 사용하고 있습니까? –

+1

교착 상태가 발생했는지 궁금합니다. 그것을 시뮬레이트하기 위해, 아마도 무한 루프 (또는 긴 수면)를 중요한 섹션에 넣고, 한 스레드 (어쩌면 관리되지 않는 루프)에서 입력 한 다음 다른 모든 스레드로부터 입력하려고 시도 할 수 있습니다. 블록? –

답변

0

실제로 DID는 가비지 수집기에서 유래합니다. WinDbg로 메모리 덤프를 디버깅 및 분석 한 후 며칠간 교착 상태가 발생했음을 알았지 만 동시에 수집하는 GC에 의해 유도되었습니다. Changing the GC to collect non-concurrently가 문제를 해결했습니다.

1

종결자는 "정상"스레드 실행과 동시에 실행됩니다. 우리는 보통 GC가 파이널 라이저를 실행한다고 말하지만 실제로 실행되어야하는 파이널 라이저가있는 인스턴스를 GC가 감지하여 전용 큐에 저장합니다. (숨겨진) 쓰레드는 큐에서 인스턴스를 가져오고 파이널 라이저를 실행합니다. 그러한 비동기가 필요합니다. 파이널 라이저 자체가 메모리를 할당하고 잠재적으로 GC를 트리거 할 수 있기 때문입니다. 파이널 라이저가 반드시 비동기적인 이유는 다른 good reasons입니다.

결론적으로 ~Hanger()을 실행할 스레드가 그 시점에 일시 중지되어 있기 때문에 ~Hanger()에서 VM이 GC 일시 중지 중에 수행하는 작업을 변경할 수 없습니다.

0

이 질문에 대한 답변을 알지 못하지만 이상한 GC 문제보다는 코드에 교착 상태가 의심됩니다.

교착 상태에 대한 코드를 확인하는 것이 좋습니다. 특히 백그라운드 스레드에서 UI 업데이트를 수행 할 때 Control.Invoke 호출과 같은 간접적 인 경우가 있습니다. Invoke을 호출 할 때 잠금을 유지하지 않도록하십시오. 예기치 않은 교착 상태가 발생할 수 있습니다 (예 : 교착 상태가 예상되는 것처럼 :)

0

Marek의 답을 뒷받침하는이 코드는 사용중인 동시성 모델의 설계 문제와 매우 유사합니다. 디자인 문제이기 때문에 테스트를 통해 효과적으로 해결할 수없는 것입니다.

내 충고는 사용중인 동시성 모델을 신중하게 고려하여 적절하게 디자인을 수정하는 것입니다. 교착 상태에 필요한 조건을 조사하여 시작하십시오 (예 :

).
  1. 어떤 상호 배타성을 보유하고 있습니까?
  2. 어떤 리소스를 이미 사용하고있는 프로세스에 추가로 필요한 리소스가 있습니까?
  3. 리소스를 사용하는 프로세스가 명시 적으로 해제되어야하는 리소스는 무엇입니까?

순환 리소스 할당 구조가있는 경우 이러한 상황을 고려하면 예상되는 교착 상태가 발생합니다.

관련 문제