2014-11-22 6 views
3

이 내 코드입니다 : C# 호출하기는 작업이 완료되지 원인

public void ReadCodes(){ 
     Task compute = Task.Run(() => 
     { 
      //foo code 
      foreach (var line in lines) 
      { 
       //some other codes 
       SetText("doing something"); 
      } 
     }); 
     compute.Wait(); 
     //some other foo 
} 
private void SetText(string text) 
{ 
     if (this.lblUsedFiles.InvokeRequired) 
     { 
       SetTextCallback d = new SetTextCallback(SetText); 
       this.Invoke(d, new object[] { text }); 
     } 
     else 
     { 
       this.lblUsedFiles.Text = text; 
     } 
} 

내가 ReadCodes() 기능이 작동 SetText("doing something") 호출을 제거

, 그렇지 않으면이 중단됩니다. 내 코드에 무슨 문제가 있습니까? Task.Run() 안에 UI를 업데이트하고 싶습니다.

+1

'Wait'은 메인 스레드를 차단하므로'Invoke' 코드를 스케쥴 할 수 없습니다. – CodesInChaos

+0

즉 교착 상태에 빠졌습니다. –

+1

'Task.Run' 다음에'task.Wait'가 완전히 무시 될 수 있습니다. 당신은 그것으로부터 어떠한 이득도 얻지 못합니다. 메서드를 동 기적으로 호출하면됩니다. –

답변

5

ReadCodes (UI 스레드에서 실행되는 것으로 추정 됨) 메서드는 새 작업을 생성하고 대기하기 위해 대기합니다. UI 스레드는 완료 될 때까지 아무 작업도 수행 할 수 없습니다.

그러나 스레드 풀에서 실행되는 작업은 Invoke을 호출하여 UI 스레드에서 작업을 실행하고이 작업이 완료 될 때까지 블로킹합니다. 두 작업이 서로를 기다리는 동안 차단되기 때문에 어느 작업도 진행될 수 없어 교착 상태가 발생합니다.

가장 쉬운 해결책은 일반적으로 InvokeBeginInvoke으로 대체하여 UI 업데이트를 기다리지 않고 작업을 계속 진행할 수있게하는 것입니다. 작업이 완료되면 UI 스레드가 해제되고 보류중인 UI 업데이트가 처리됩니다.

편집 : 루프를 포함하도록 업데이트되는 질문에 대한 응답으로 : (C# 5에서 도입 된) 비동기 패턴을 사용하는 것이 좋습니다. 이렇게하면 UI 스레드 차단이 모두 제거되고 각 행이 처리되는 즉시 UI 업데이트를 수행 할 수 있습니다.

public async Task ReadCodes() 
{ 
    foreach (var line in lines) 
    { 
     string text = await Task.Run(() => 
     { 
      //foo code 
      // return text; 
     }); 

     this.lblUsedFiles.Text = text; 
    } 
    //some other foo 
} 

편집 : Peter Duniho's comment에 따라 내 코드를 업데이 트했습니다. ReadCodes은 아마도 UI 스레드에서 호출되기 때문에 각 작업을 기다리는 즉시 Invoke이 필요하지 않고 UI를 직접 업데이트 할 수 있습니다. //some other codes에서 수행 된 백그라운드 처리가 후속 반복의 //foo code에 통합 될 수 있다고 가정합니다.

+0

'HandToo()'가 실제로'foreeach' 루프 내에서 호출되기 때문에'it.Run()'안의 모든 반복에서 UI를 업데이트하지 않습니다. 최신 반복에서만 UI를 업데이트합니다. – Maysam

+0

주된 문제는'Invoke'가 아니라 메인 스레드에서'Wait'을 호출하는 것입니다. – CodesInChaos

+0

@CodesInChaos'Task.Run()'내부의 코드 실행이 완료 될 때까지 기다리는 동시에 UI를 업데이트하려고합니다. – Maysam

관련 문제