2013-05-25 10 views
9

Jak nie wiem dużo o wątkach, mam pytanie. Chcę zrobić coś w tle iw metodzie tła Chcę przełączyć się z powrotem do głównego wątku pod pewnymi warunkami, inaczej będzie działał w tle. Jak mogę osiągnąć tę funkcjonalność? Używam wywołanie StartSyncThread z klasy UI (C#)Oddzwon do głównego wątku z Zadania

async void StartSyncThread() 
{ 
    await DoSyncAsync(); 
} 

Task DoSyncAsync() 
{ 
    return Task.Run(() => DoSync());    
} 

w metodzie DoSync chcę wrócić do głównego wątku, tak, że mogę zmienić UI. Proszę, daj mi proste rozwiązanie, aby to zrobić. Z góry dziękuję!

+0

Sprawdź "Control.Invoke (()" lub ten wątek: http://stackoverflow.com/questions/4331262/task-continuation-on-ui-thread –

Odpowiedz

6

Najpierw uruchom proces asynchroniczny, a następnie wywołaj Dispatcher.BeginInvoke, aby powrócić do wątku interfejsu użytkownika.

Task.StartNew(() => 
{ 
    // Do Something Async 

    Dispatcher.BeginInvoke(() => 
    { 
     // Update Your UI Here 
    }); 
}); 

Zauważ, że dyspozytor nie jest statyczna - ten opiera się na kodzie bycia częścią funkcji składowej dla obiektu UI, jak metody na swojej stronie obiektu.

8

Istnieje kilka podejść.

Pierwsza polega na podzieleniu metody synchronicznej na różne części. Jest to najlepsze, jeśli twoja metoda synchroniczna oblicza różne typy rzeczy, które trafiają do różnych części interfejsu użytkownika:

async Task DoSyncAsync() 
{ 
    myDataBoundUIProperty1 = await Task.Run(() => DoSync1()); 
    myDataBoundUIProperty2 = await Task.Run(() => DoSync2()); 
} 

Drugi to używanie raportów z postępów. Jest to najlepsze, jeśli aktualizacje interfejsu użytkownika są tego samego typu:

Task DoSyncAsync() 
{ 
    Progress<MyProgressType> progress = new Progress<MyProgressType>(progressUpdate => 
    { 
    myDataBoundUIProperty = progressUpdate; 
    }); 
    return Task.Run(() => DoSync(progress)); 
} 
void DoSync(IProgress<MyProgressType> progress) 
{ 
    ... 
    if (progress != null) 
    progress.Report(new MyProgressType(...)); 
    ... 
} 

Istnieje ostateczna alternatywa, ale zdecydowanie polecam jedną z powyższych dwóch. Dwa powyższe rozwiązania spowodują lepszą konstrukcję kodu (separacja problemów). Trzecią alternatywą jest przekazać w TaskFactory, które mogą być wykorzystane do uruchomienia dowolnego kodu w kontekście Ui:

Task DoSyncAsync() 
{ 
    var scheduler = TaskScheduler.FromCurrentSynchronizationContext(); 
    var factory = new TaskFactory(scheduler); 
    return Task.Run(() => DoSync(factory)); 
} 
void DoSync(TaskFactory factory) 
{ 
    ... 
    scheduler.StartNew(() => { ... }); 
    ... 
} 

Ponownie, nie radzę to ostatnie rozwiązanie, gdyż zrównują swoją logikę aktualizacji UI z zadania w tle logika. Ale lepiej jest, niż bezpośrednio używać Dispatcher lub.

Powiązane problemy