Wybierz metodę System.Windows.Forms.Control.Invoke (metoda delegata)
Dlaczego powoduje to błąd czasu kompilacji:
string str = "woop";
Invoke(() => this.Text = str);
// Error: Cannot convert lambda expression to type 'System.Delegate'
// because it is not a delegate type
Ale to działa dobrze:
string str = "woop";
Invoke((Action)(() => this.Text = str));
Kiedy metoda oczekuje zwykłego delegata?
Invoke(()=>DoStuff)
i nadal otrzymuję błąd. Problem polegał na tym, że użyłem domyślnego „tego”. Aby zmusić go do pracy z wnętrza elementu sterującego trzeba być jednoznaczne:this.Invoke(()=>DoStuff)
.Masz dość ciągłego rzucania lambd?
źródło
Lambda<T>
klasa ma wywołaną metodę konwersji tożsamościCast
, która zwraca wszystko, co zostało przekazane (Func<T, T>
). TerazLambda<T>
jest zadeklarowane jako,Lambda<Func<int, string>>
co oznacza, że jeśli przekażesz metodęFunc<int, string>
doCast
, powróci ona zFunc<int, string>
powrotem, ponieważT
w tym przypadku jestFunc<int, string>
.Dziewięć dziesiątych przypadków ludzie to rozumieją, ponieważ próbują skierować się do wątku interfejsu użytkownika. Oto leniwy sposób:
Teraz, gdy jest wpisany, problem znika (odpowiedź Skeeta) i mamy bardzo zwięzłą składnię:
Jeśli chodzi o punkty bonusowe, oto kolejna wskazówka. Nie zrobiłbyś tego dla elementów interfejsu użytkownika, ale w przypadkach, w których potrzebujesz SomeMethod do blokowania aż do zakończenia (np. Żądanie / odpowiedź I / O, oczekiwanie na odpowiedź) użyj WaitHandle (qv msdn WaitAll, WaitAny, WaitOne).
Należy zauważyć, że AutoResetEvent jest pochodną WaitHandle.
I ostatnia wskazówka, ponieważ rzeczy mogą się zaplątać: WaitHandles blokuje nić. To właśnie powinni zrobić. Jeśli spróbujesz skierować do wątku interfejsu użytkownika, gdy jest on zablokowany , aplikacja się zawiesi. W takim przypadku (a) konieczna jest poważna refaktoryzacja i (b) jako tymczasowy hack możesz poczekać w ten sposób:
źródło
System.Windows.Threading.Dispatcher.CurrentDispatcher
zwróci dyspozytor wątku CURRENT - tzn. jeśli wywołasz tę metodę z wątku, który nie jest wątkiem interfejsu użytkownika, kod nie zostanie uruchomiony w wątku interfejsu użytkownika.Peter Wone. jesteś człowiekiem. Idąc nieco dalej, wymyśliłem te dwie funkcje.
Umieszczam te dwie funkcje w mojej aplikacji Form i mogę nawiązywać połączenia z takimi pracownikami w tle
Może trochę leniwy, ale nie muszę konfigurować funkcji wykonanych przez pracownika, co jest bardzo przydatne w takich przypadkach
Zasadniczo pobierz adresy IP z gui DataGridView, wyślij do nich ping, ustaw wynikowe ikony na zielone lub czerwone i ponownie włącz przyciski w formularzu. Tak, jest to „parallel.for” w pracującym w tle. Tak, to DUŻO wywoływania narzutu, ale jest to pomijalne w przypadku krótkich list i znacznie bardziej zwartego kodu.
źródło
Próbowałem to zbudować na odpowiedzi @Andrey Naumov . Może to jest niewielka poprawa.
Gdzie parametr typu
S
jest parametrem formalnym (parametrem wejściowym, który jest minimalny wymagany do wywnioskowania pozostałych typów). Teraz możesz to nazwać tak:Możesz mieć dodatkowe przeciążenia dla
Action<S>
iExpression<Action<S>>
podobnie w tej samej klasie. Na drugi zbudowany w typów delegatów i wypowiedzi, trzeba będzie napisać osobne zajęcia, takie jakLambda
,Lambda<S, T>
,Lambda<S, T, U>
itd.Zaleta tego, którą widzę w porównaniu z oryginalnym podejściem:
Jedna specyfikacja typu mniej (należy podać tylko parametr formalny).
Co daje ci swobodę użycia go przeciwko każdemu
Func<int, T>
, nie tylko wtedy, gdyT
jest powiedzstring
, jak pokazano na przykładach.Obsługuje wyrażenia od razu. We wcześniejszym podejściu będziesz musiał ponownie określić typy, takie jak:
dla wyrażeń.
Rozszerzanie klasy dla innych typów delegatów (i wyrażeń) jest podobnie nieporęczne, jak powyżej.
W moim podejściu musisz zadeklarować typy tylko raz (to za jeden mniej na
Func
s).Innym sposobem na wdrożenie odpowiedzi Andreya jest nie przejście w pełni na ogólny
Więc wszystko sprowadza się do:
To jeszcze mniej pisania, ale tracisz pewne bezpieczeństwo typów, a imo, to nie jest tego warte.
źródło
Trochę za późno na imprezę, ale możesz też tak przesyłać
źródło
źródło
Grając z XUnit i Fluent Assertions , udało mi się wykorzystać tę wbudowaną możliwość w sposób, który uważam za naprawdę fajny.
Przed
Po
źródło