2011-09-28 5 views
2

진행중인 Winforms 컨트롤 (DataGridView)을 업데이트해야하는 멀티 스레드 응용 프로그램에서 작업하고 있습니다. 나는 다음 DGV가 UI 스레드에서 생성 된 이후, 그것은 .Invoke() '라 할 필요가 있음을 깨달았다Lock (Control) 대신 Control.Invoke() 사용

if (DGV.Columns.Count >= DesiredColumnCount) return; 
lock(DGV) 
{ 
    while (DGV.Columns.Count < DesiredColumnCount) 
    { 
     DGV.Columns.Add(newColumn); 
    } 
} 

: 같은 공유 리소스에 다중 접속을 방지하기 위해, 나는 다음과 같은 잠금 구조로 시작 . 그러면 코드가 다음과 같이 변경됩니다.

if (DGV.Columns.Count >= DesiredColumnCount) return; 
lock(DGV) 
{ 
    DGV.Invoke(new MethodInvoker(() => 
     { 
      while (DGV.Columns.Count < DesiredColumnCount) 
      { 
       DGV.Columns.Add(newColumn); 
      } 
     } 
} 

내 질문은 : 중복이 아닙니까? lock은 단독 스레드가 DGV에 액세스 할 때까지 작업자 스레드를 차단하고 Invoke()은 UI 스레드가 호출 요청을 받아서 코드를 실행할 때까지 작업자 스레드를 차단합니다. Invoke() 만 사용하면 안 될까요?

(즉. 주요 질문은 위의 코드에서 다른 멀티 스레딩 죄가 있다면 물론, 의견을주세요) 그것은 조금 중복

+0

"작업자 스레드"에 대해 무엇을 사용하고 있습니까? –

+0

UI 스레드를 절대로 차단해서는 안됩니다. Control 및 Invoke뿐만 아니라 잠금도 마찬가지입니다. 잠금을 제거하고 Invoke to BeginInvoke를 변경해야합니다. –

+0

@ PeterRitchie 정확하게 스레드를 시작한 것을 기억하지 못합니다. 아마도 새로운 스레드(). Start() 또는 System.Threading.Timer.Elapsed입니다. 이 코드는 UI 스레드를 차단하지 않았으므로 작업자를 차단했을 것입니다. BeginInvoke는 호출자를 차단하지 않으므로 Invoke를 맹목적으로 대체 할 수 없습니다. 호출 순서를 잘못 지정하여 서로의 순서가 잘못되어 실행되지 않도록해야합니다. 이는 작업자 스레드를 차단하는 데 소요되는 시간을 줄여 성능을 향상시킬 수 있지만 지금까지는 오래된 프로젝트입니다. – Nathan

답변

3

UI를 위해, Invoke 호출 것 "파견"는 operpation 실. 연속적인 각각의 Invoke 호출은 직렬 방식으로 전달되므로 실제로 잠금을 수행 할 필요가 없습니다.

작업자 스레드가 막히지 않도록 Invoke 명령 대신 BeginInvoke을 사용하는 것이 좋지만 잠금을 걱정할 필요가 없도록 "직렬"로 수행됩니다.

+0

게시물을 보내 주셔서 감사하지만 혼란 스러워요. Skeet은 Control.Invoke가 UI 스레드에서 실행되고 완료 될 때까지 대기한다고 (http://stackoverflow.com/questions/229554/whats-the-difference-between-invoke-and-begininvoke) 말합니다. – Nathan

+0

예, 그는 BeginInvoke()에 대해 이야기하고 있습니다. 상관 없어요, 자물쇠가 필요 없어요. 모든 코드는 동일한 스레드에서 실행되므로 데이터를 보호 할 필요가 없습니다. –

+2

그 잠금 장치가 중복 될뿐만 아니라, 교착 상태가 발생하기를 기다리고 있습니다. Invoke에 대한 호출 중에 호출 된 일부 코드가 잠금을 얻으려고하면 스레드가 잠금을 유지하고 UI 스레드에서 'Invoke'가 완료 될 때까지 기다리고 UI 스레드가 기다리고 있기 때문에 멈춘 것입니다 자물쇠를 얻기 위해. –