2012-05-22 2 views
1

모두, 배경 스레드에서 실행되는 일부 무거운 리프팅 Task 있습니다. 내가 설정 한 방식은 이것이 완료되는 동안 UI 스레드가 진행 정보로 GUI를 업데이트하며 일부는 애니메이션 .gif 파일을 사용합니다. TPL BackgroundThread UIThread 그래픽 업데이트

TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 
Task<bool> task = Task.Factory.StartNew(() => 
{ 
    // Heavy work. 
    if (heavyWorkCompleted) 
     MethodToUpdateGui(uiScheduler); // Update DataGridView ImageCell on UI thread 
    // More work. 
} 

내가 "무거운 작업이" "무거운 작업"의 실행 중에 적절한 DGV 이미지 셀에 표시되는 "진행 중"이미지입니다 경우 문제를 설명하기 위해 다음 예제 코드를 살펴 보자 성공적으로이 이미지가 틱 (DGV1)으로 변경되면 MethodToUpdateGui(uiScheduler)은 DGV1에서이 (변경된) 이미지를 사용하여 DGV2를 업데이트합니다. 그러나 MethodToUpdateGui(uiScheduler)이 실행되면 DataGridView (DGV2)가 너무 빨리 업데이트되는 경우가 있습니다. 이것이 의미하는 바는, 이미지가 내가 원하는 진드기가 아니라는 것입니다 (그리고 성공적인 완성으로 인해 야합니다). 그것은 "진행 중"이미지입니다. DGV가 내가하는 일에 대해 충분히 빠르게 업데이트하지 않는 것 같습니다.

더 좋은 방법이 있나요? GUI 업데이트 후 DGV1이 "따라 잡을"수 있도록 백그라운드 스레드를 돌릴 수 있습니까?

감사합니다.

답변

1

더 좋은 방법이 있나요? GUI 업데이트 후 DGV1이 "따라 잡을"수 있도록 백그라운드 스레드를 돌릴 수 있습니까?

여기서 TPL은 SynchronizationContext.Post을 사용하여 메시지를 UI 스레드로 보냅니다. 메서드가 실행되면 Task가 비동기 적으로 실행되고 GUI가 즉시 업데이트되지 않습니다.

GUI가 업데이트되었는지 확인하려면 uiScheduler을 통해 예약 된 작업을 기다려서 MethodToUpdateGui 블록을 차단하는 것이 가장 간단한 옵션입니다.

void MethodToUpdateGui(TaskScheduler uiScheduler) 
{ 
    var updateTask = Task.Factory.StartNew(() => 
    { 
     // update gui 
    }, CancellationToken.None, TaskCreationOptions.None, uiScheduler); 

    // Block until Task completes... 
    updateTask.Wait(); 
} 

이 그것을 차단하고 자동으로 TPL 통보받을로, 회전하는 것보다 낫다 :

이 같이 보일 것입니다.

Windows Forms 용어에서 Control.BeginInvoke 대신 실제로 Control.Invoke을 사용하고 있습니다.

+0

저는 실제로 이것을합니다. 'uiScheduler'를 사용하는 모든 GUI 업데이트에서 나는'uiTask.Wait()'(모든'AggregateException'을 잡으려고'try/catch '로 싸서)를 사용합니다. 그러나이 "레이싱"은 여전히 ​​일어나고 있습니다! 혼란 스럽네요 ... – MoonKnight

+0

@Killercam "완료"메시지를 똑같이하고 있습니까? –

+0

완료 메시지는 연속으로 처리됩니다. 나는 계속을 기다리지 않으며,이 문제가 발생한 후에도 계속 대표가 호출된다. – MoonKnight