2016-08-08 3 views
0

저는 C#Task을 처음 사용하고 스레딩하고 있습니다.C# UI 업데이트 작업

나는 코드 아래와 같이있다 : -

public void UpdateSales(object sender, EventArgs args) 
{ 
    Task.Run(() => 
    { 
    // Some code Create Collection ... 
    // Some code with business logic .. 


    // Below code is to update UI 
    // is it safe to update UI like below 

     saleDataGrid.Dispatcher.Invoke((Action) (() => 
           { 

            saleDataGrid.ItemsSource = currentCollection; 
            saleDataGrid.Items.Refresh(); 
           })); 

    }); 
} 

이 코드가 정확인지 아닌지 확실하지 않다. 어쨌든 교착 상태가 발생할 수 있다고 생각합니까?

작업에서 UI를 어떻게 업데이트 할 수 있습니까? UpdateSales은 타사 라이브러리의 이벤트 처리기이기 때문에 async/await을 사용하지 않습니다.

+2

일반적으로 Dispatcher를 호출하고 특정 스레드에서 호출해야하는지 확인하기 만하면됩니다. 하지만 당신의 코드가 교착 상태를 일으키지 않을 것이라고 확신합니다. –

답변

6

UpdateSales는 UI 스레드에서 호출된다고 가정을, 청소기 솔루션이 될 것이다 :

public async void UpdateSales() 
{ 
    var collection = await Task.Run(() => 
    { 
    // Some code Create Collection ... 
    // Some code with business logic .. 
    return currentCollection; 
    }); 
    saleDataGrid.ItemsSource = collection; 
    saleDataGrid.Items.Refresh(); 
} 

내 블로그에 설명으로 , await will automatically resume on a captured context (이 경우 UI 컨텍스트). 나는 Dispatcher이 아니라 await이라는 암시 적 컨텍스트를 직접 사용하는 편이 더 좋습니다. 코드는 더 짧고 이식성이 좋습니다.

+0

'UpdateSales' 이벤트가 COM 오브젝트 이벤트 핸들러에서 실행 중입니다. UI 스레드인지 확실하지 않습니다. 이 메서드 시그니처를 올바르게 편집하기 위해이 시그니처를 편집했습니다. –

5

아시다시피, Task.Run은 스레드 풀 스레드에서 실행됩니다.

당신은 그 작업이 완료 될 때 실행하는 ContinueWith 사용할 수 있습니다 - 당신이 허용하는 one of the overrides을 선택하면 당신은이 TaskScheduler 당신은 당신이 방법을 입력 동기화 컨텍스트를 사용합니다 TaskScheduler.FromCurrentSynchronizationContext()을 사용할 수 있습니다 지정 - 그것이 UI 스레드 인 경우 (예를 들어 UI 이벤트의 이벤트 핸들러에있는 경우) 동기화 컨텍스트는 UI 스레드의 컨텍스트가됩니다.

그래서 코드는 다음과 같이 보일 것이다 :

Task.Run(() => { 
        ...code to create collection etc... 
       } 
     ) 
     .ContinueWith(() => { 
           saleDataGrid.ItemsSource = currentCollection; 
          } 
         , TaskScheduler.FromCurrentSynchronizationContext() 
        );