2009-10-02 2 views
0

특정 COM 메서드 호출에 대해 우리가 가지고있는 서비스 (C#으로 작성 됨)에 대한 고정 시간을 설정해야했습니다. Thread.Sleep 이외의 System.Threading 네임 스페이스를 사용하는 데 아니, 나는 연극이 있고 프로토 타입과 함께 올라와있다 :이 방법C# 코드에서 COM 메서드 호출을 효과적으로 시간 종료하는 방법

bool _comCallSuccessful = false; 
bool _timedOut = false; 

private void MakeACOMCallThatCouldTakeALongTime() 
{ 
    Thread.Sleep(2500); 
    _comCallSuccessful = true; 
} 

private void CheckForOneSecondTimeOut() 
{ 
    Thread.Sleep(1000); 
    _timedOut = true; 
} 

private void ThreadTester() 
{ 
    Thread t1 = new Thread(new ThreadStart(MakeACOMCallThatCouldTakeALongTime)); 
    Thread t2 = new Thread(new ThreadStart(CheckForOneSecondTimeOut)); 

    t1.Start(); 
    t2.Start(); 

    while (!_timedOut && !_comCallSuccessful) { } 

    if (_comCallSuccessful) 
    { 
     Console.WriteLine("Finished!"); 
    } 
    else 
    { 
     t1.Abort(); 
     Console.WriteLine("Timed out!"); 
    } 
    Console.ReadLine(); 
} 

실질적으로 말하기, 거기 어떤 문제? 예를 들어 COM 메서드 호출을 만드는 스레드를 중단하려는 경우 (예 : 사용 된 리소스를 정리하는 등) 문제가 있습니까?

답변

2

Thread.Abort() is always a problem.

COM 서버에 대해 아는 것이 있습니까? 프로세스 내에서 또는 프로세스 외부에서 또는 원격으로 실행됩니까? COM 서버가 버그가있어서 실제로 종료해야하는 경우 안전하게 종료 할 수있는 희생 프로세스 (또는 적어도 별도의 AppDomain)에서 호출을 래핑하는 것이 좋습니다. (그리고 아마도 부정 행위를하여 불쾌한 COM 응용 프로그램을 종료 할 수 있습니다. 잘). 도울 수있는 경우 자체 프로세스에서 스레드를 중단하지 마십시오. 그것은 바보의 cyles을 보내고 당신의 CPU를 만드는 것이므로 내가 추가해야합니다

1

큰 문제 : 대부분의 경우 작동하지 않습니다. COM 스레드가 Abort()를 호출 할 때 원시 코드에서 사용 중이면 아무 일도 일어나지 않습니다. 스레드가 관리되는 코드로 돌아 오면 ThreadAbortException이 나타납니다. 관리되지 않는 코드 호출을 중단 할 수있는 100 % 신뢰할만한 방법은 없습니다. 근본적인 OS 쓰레드를 죽이려고 시도 할 수는 있지만 CLR은 그것에 잘 응답하지 않을 것이므로 프로세스가 불안정해질 수 있습니다.

+0

좋은 지점에서 작업을 취소 할 수있는 명시 적 방법이있을 것이다. – jpoh

1

이미

while (!_timedOut && !_comCallSuccessful) { } 

처럼 기다리고 있다는 다른 의견 제시 언급하는 것은 잘못된 것입니다.

EventwaitHandle _comCallSuccessful = new ManualResetEvent(false); 
EventwaitHandle _timedOut = new ManualResetEvent(false); 
private void MakeACOMCallThatCouldTakeALongTime() { 
    Thread.Sleep(2500); 
    _comCallSuccessful.Set(); 
} 

private void CheckForOneSecondTimeOut() { 
    Thread.Sleep(1000); 
    _timedOut.Set(); 
} 

private void ThreadTester() { 
    /* thread starting*/ 
    var handles = new WaitHandle[]{_comCallSuccessful, _timedOut}; 
    int indexFirstSet = Waithandle.WaitAny(handles); 
    if (indexFirstSet == 0) // _comCallSuccessful 
    { 
     Console.WriteLine("Finished!"); 
    } 
    else 
    { 
     t1.Abort(); 
     Console.WriteLine("Timed out!"); 
    } 
} 

메인 스레드에서 아무 상관이 없다면, 당신은 하나 개의 스레드를 시작하고 반환 _comCallSuccessful.WaitOne (타임 아웃)을 사용할 수 있습니다 :

당신은 System.Threading.EventWaitHandle를 사용하는 것이 좋습니다 거라고 이벤트가 타임 아웃 전에 Set() 인 경우는 true

어쨌든, 당신은 더 나은 서비스 (예를 들어, COM 개체 방법) Thread.Abort은 네이티브 코드 호출을 중단 할 수 없다는 대한

+0

팁 주셔서 감사! – jpoh

관련 문제