2015-02-02 6 views
0

나는이 같은 뮤텍스를 사용하여 내 응용 프로그램에서 백그라운드 스레드가 있습니다뮤텍스 블록 UI 스레드

void bgWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     MyMutex.MuImageLock.WaitOne();     
     foreach (var file in ImageFiles) 
     { 
      SyncFileToLocalImage(file.FileNameNoPath); 
     } 
     MyMutex.MuImageLock.ReleaseMutex();   
    } 

을 그리고 동기화 2-3 분 정도 걸립니다. 이제는 내 응용 프로그램에 배경 스레드가 하나 더있어 동일한 작업을 수행합니다.

제 2 번째 스레드를 시작하기 전에 뮤텍스를 사용할 수 있는지 확인하고 싶습니다. 사용할 수 없다면 다른 스레드가 실행 중임을 의미하므로이 새 스레드를 시작할 필요가 없습니다. 그래서 내가 아래 코드를 사용하는지 확인해보십시오.

아래 코드를 사용하면 WaitOne 메서드는 이전 스레드가 뮤텍스를 해제하지 않을 때까지 내 UI 스레드를 차단합니다.

if (MyMutex.MuImageLock.WaitOne()) 
{ 
    getPRImages(); 
    MyMutex.MuImageLock.ReleaseMutex(); 
} 

현재 UI 스레드를 차단하고 싶지 않습니다. 뮤텍스를 사용할 수 있는지 확인하고 싶습니다. 내가 어떻게 그럴 수 있니?

+0

시간 초과를 허용하는 ['WaitOne'] (https://msdn.microsoft.com/en-us/library/cc189907(v=vs.110) .aspx) 오버로드를 사용할 수 있습니다. 타임 아웃을 밀리 초로 설정하고 반환 값에 따라 타임 아웃을 가져올 수 있는지 확인합니다. – vcsjones

+0

차단을 피하려면 백그라운드 스레드에서 기다릴 수 있습니다. .net의 어떤 버전을 사용하고 있습니까? 당신이 무엇을 사용하고 있는지에 따라 다른 접근 방식이 있습니다. – Dbl

+0

VS 2013을 사용하고 있습니다.뮤텍스가 출시되었을 때 해고 당할 수있는 이벤트가 있는지 알고 싶습니다. –

답변

0

코드 예제에서 백그라운드 스레드 자체를 제외하고는 BackgroundWorker의 기능을 사용하지 않는 것 같습니다. 따라서이 접근하는 올바른 방법은 단순히 백그라운드 프로세스를 시작하는 플래그를 유지하고 Task.Run()을 사용하는 것입니다 :

private bool _isRunning; 

private async void Button_Click(object sender, RoutedEventArgs e) 
{ 
    if (_isRunning) 
    { 
     return; 
    } 

    _isRunning = true; 
    await Task.Run(() => SyncAllFiles()); 
    _isRunning = false; 

    // Populate ListBox here 
} 

private void SyncAllFiles() 
{ 
    foreach (var file in ImageFiles) 
    { 
     SyncFileToLocalImage(file.FileNameNoPath); 
    } 
} 

참고 : 위에서, 나는 동기화가 시작됩니다 일부 UI 버튼이 가정합니다. 불행히도 질문에 문맥을 이해할 수있는 완전한 코드 예제가 포함되어 있지 않습니다. 버튼이 아니라면 특정 시나리오에 맞게 위의 내용을 적용 할 수 있습니다.

진행 상황을보고하고 질문의 코드 예제에서 벗어난 경우에도 위의 작업을 수행 할 수 있습니다. Progress<T> 클래스를 사용하여 그 인스턴스를 SyncAllFiles() 메서드로 전달하고 IProgress<T>.Report() 메서드를 호출하여 실제로 진행률을보고합니다. 이것은 BackgroundWorker.ProgressChanged 이벤트와 같은 방식으로 작동합니다 (UI 스레드에서 Progress<T> 오브젝트를 생성하는 한 이벤트 핸들러는 UI 스레드에서 호출됩니다).

위와 비교해도 사용자가 작업을 다시 시작하고 완료 될 때만 다시 사용하도록 설정할 수있는 버튼이나 기타 UI 요소를 비활성화하는 것이 훨씬 더 좋습니다.


마지막 : 나는 Mutex 클래스를 사용할 수있는 실제적인 방법이 생각하지 않습니다 (당신이 게시물에 국한되지 않는,하지만 난 당신이 System.Threading.Mutex을 사용한다고 가정). 뮤텍스에 따라 작업을 조정하고 UI 스레드는 단지 해결하기 어려운 경쟁 조건을 요구하는 것처럼 보입니다. 예 : 백그라운드 스레드가 시작되어 뮤텍스를 획득하기 전에 연속적으로 두 번 클릭 이벤트가 발생하면 어떻게됩니까? 그것은 그것이 잘못 될 수있는 많은 가능한 방법 중 하나 일뿐입니다.

상태를 완전히 단일 스레드로 관리함으로써 위의 제안 된 솔루션은 모든 경쟁 조건이 직접 처리되도록합니다.

+0

'뮤텍스 (mutex) '는 스레드 동기화 메커니즘을 차단하는 한 형태라고 지적하는 것이 가치 있다고 생각합니다. 이는 UI 스레드를 쉽게 차단할 수 있다는 것을 의미합니다. UI 스레드는 먼저 클라이언트 응용 프로그램에서 다중 스레드 지점을 무력화시킵니다. – Aron