Słyszałem gdzieś, że asynchroniczne oczekiwanie na C # 5 będzie tak niesamowite, że nie będziesz musiał się tym martwić:
if (InvokeRequired)
{
BeginInvoke(...);
return;
}
// do your stuff here
Wygląda na to, że wywołanie zwrotne operacji oczekującej nastąpi w oryginalnym wątku osoby dzwoniącej. Eric Lippert i Anders Hejlsberg kilkakrotnie stwierdzili, że ta funkcja powstała w wyniku potrzeby lepszego reagowania interfejsów użytkownika (szczególnie interfejsów urządzeń dotykowych).
Myślę, że częstym użyciem takiej funkcji byłoby coś takiego:
public class Form1 : Form
{
// ...
async void GetFurtherInfo()
{
var temperature = await GetCurrentTemperatureAsync();
label1.Text = temperature;
}
}
Jeśli zostanie użyte tylko wywołanie zwrotne, ustawienie tekstu etykiety spowoduje wyjątek, ponieważ nie jest ono wykonywane w wątku interfejsu użytkownika.
Jak dotąd nie mogłem znaleźć żadnych zasobów potwierdzających, że tak jest. Czy ktoś o tym wie? Czy są jakieś dokumenty wyjaśniające technicznie, jak to będzie działać?
Podaj link z wiarygodnego źródła, nie odpowiadaj tylko „tak”.
źródło
await
funkcjonalności. To tylko dużo cukru syntaktycznego do kontynuacji . Być może istnieją inne niepowiązane ulepszenia WinForm, które powinny pomóc? To byłoby objęte samą platformą .NET, a nie C #.Odpowiedzi:
Myślę, że tutaj wprowadzasz kilka rzeczy w błąd. Co pytasz, jest już możliwe przy użyciu
System.Threading.Tasks
Theasync
aawait
w C # 5 są właśnie zamierza dostarczyć trochę ładniejszy cukier syntaktyczny dla tej samej funkcji.Użyjmy przykładu Winforms - upuść przycisk i pole tekstowe na formularzu i użyj tego kodu:
Uruchom go, a zobaczysz, że (a) nie blokuje wątku interfejsu użytkownika i (b) nie pojawia się zwykły błąd „niepoprawna operacja wielowątkowa” - chyba że usuniesz
TaskScheduler
argument z ostatniegoContinueWith
, w w którym przypadku będziesz.Jest to standardowy sposób przekazywania kontynuacji . Magia dzieje się w
TaskScheduler
klasie, a konkretnie w instancji, którą odzyskujeFromCurrentSynchronizationContext
. Przekaż to do dowolnej kontynuacji, a powiesz, że kontynuacja musi działać na dowolnym wątku o nazwieFromCurrentSynchronizationContext
metoda - w tym przypadku na wątku interfejsu użytkownika.Oczekujący są nieco bardziej wyrafinowani w tym sensie, że są świadomi, w którym wątku rozpoczęli i w którym wątku musi nastąpić kontynuacja. Tak więc powyższy kod można napisać nieco bardziej naturalnie:
Te dwa powinny wyglądać bardzo podobnie, a w rzeczywistości są bardzo podobne.
DelayedAddAsync
Metoda teraz zwracaTask<int>
zamiastint
, a więcawait
jest tylko bicie kontynuacje na każdym z nich. Główną różnicą jest to, że przechodzi przez kontekst synchronizacji w każdej linii, więc nie musisz robić tego wyraźnie, jak to zrobiliśmy w poprzednim przykładzie.Teoretycznie różnice są znacznie bardziej znaczące. W drugim przykładzie każda pojedyncza linia w
button1_Click
metodzie jest faktycznie wykonywana w wątku interfejsu użytkownika, ale samo zadanie (DelayedAddAsync
) działa w tle. W pierwszym przykładzie wszystko działa w tle , z wyjątkiem przypisania, dotextBox1.Text
którego wyraźnie przypisaliśmy kontekst synchronizacji wątku interfejsu użytkownika.To jest naprawdę interesujące
await
- fakt, że oczekujący jest w stanie wskoczyć i wyjść z tej samej metody bez blokowania wywołań. Dzwoniszawait
, bieżący wątek wraca do przetwarzania wiadomości, a kiedy to się skończy, oczekujący wybierze dokładnie tam, gdzie go przerwał, w tym samym wątku, w którym przerwał. Ale jeśli chodzi o twójInvoke
/BeginInvoke
kontrast w pytaniu, ja ' Przykro mi to mówić, że powinieneś przestać to robić dawno temu.źródło
ArrayList
klasy w nowym kodzie. Sam wciąż nie mam prawie żadnego doświadczenia z RX. Ludzie dowiadują się, co powinni wiedzieć, i dzielą się tym, co już wiedzą, nawet jeśli to, co już wiedzą, jest nieaktualne. Ta odpowiedź może być nieaktualna za kilka lat.Tak, w przypadku wątku interfejsu użytkownika wywołanie zwrotne operacji oczekującej nastąpi w oryginalnym wątku osoby wywołującej.
Eric Lippert napisał o tym 8-częściową serię rok temu: Fabulous Adventures In Coding
EDYCJA: a tutaj // kompilacja / prezentacja Andersa: Andersa channel9
BTW, czy zauważyłeś, że jeśli wywrócisz „// build /” do góry nogami, otrzymasz „/ plinq //” ;-)
źródło
Jon Skeet wygłosił doskonałą prezentację obejmującą metody asynchroniczne w C # 5, które mogą okazać się niezwykle przydatne:
http://skillsmatter.com/podcast/home/async-methods
źródło