Jak rozpocząć wątek z parametrami w C #?
c#
multithreading
J L.
źródło
źródło
Odpowiedzi:
Tak :
źródło
void MyParamObject(object myUrl){ //do stuff }
powinien mieć typ parametruobject
ParameterizedThreadStart
i wyraźnie z tekstu pytania, prawdopodobnie tak nie jest.Jedno z 2 przeciążeń konstruktora wątków pobiera delegata ParameterizedThreadStart, który pozwala przekazać pojedynczy parametr do metody startowej. Niestety dopuszcza tylko jeden parametr i robi to w niebezpieczny sposób, ponieważ przekazuje go jako obiekt. Uważam, że o wiele łatwiej jest użyć wyrażenia lambda, aby uchwycić odpowiednie parametry i przekazać je w mocno typowy sposób.
Spróbuj wykonać następujące czynności
źródło
Dim thr As New Thread(Sub() DoStuff(settings))
Możesz użyć wyrażeń lambda
to jak dotąd najlepsza odpowiedź, jaką mogłem znaleźć, jest szybki i łatwy.
źródło
Typ parametru musi być obiektem.
EDYTOWAĆ:
Chociaż ta odpowiedź nie jest niepoprawna, odradzam takie podejście. Korzystanie z wyrażenia lambda jest znacznie łatwiejsze do odczytania i nie wymaga rzutowania tekstu. Zobacz tutaj: https://stackoverflow.com/a/1195915/52551
źródło
Parameter
?źródło
Prosty sposób z wykorzystaniem lambda tak…
LUB możesz nawet
delegate
użyćThreadStart
tak ...LUB przy użyciu VS 2019 .NET 4.5+ jeszcze czystszy tak ..
źródło
Zastosowanie
ParametrizedThreadStart
.źródło
Użyj ParameterizedThreadStart .
źródło
Jak już wspomniano w różnych odpowiedziach tutaj,
Thread
klasa obecnie (4.7.2) zapewnia kilka konstruktorów iStart
metodę z przeciążeniami.Tymi odpowiednimi konstruktorami tego pytania są:
i
które biorą
ThreadStart
delegata lubParameterizedThreadStart
delegata.Odpowiedni delegaci wyglądają tak:
Jak można zauważyć, poprawnym konstruktorem do użycia wydaje się być ten, który bierze
ParameterizedThreadStart
delegata, aby pewna metoda zgodna z określoną sygnaturą delegata mogła zostać uruchomiona przez wątek.Prostym przykładem
Thread
byłoby zainicjowanie klasyLub tylko
Podpis odpowiedniej metody (wywołanej
Work
w tym przykładzie) wygląda następująco:Pozostało rozpocząć wątek. Odbywa się to za pomocą jednego z nich
lub
Chociaż
Start()
uruchamia wątek i przekazujenull
dane do metody,Start(...)
może służyć do przekazywania wszystkiego doWork
metody wątku.Jest jednak jeden duży problem z tym podejściem: wszystko przekazane do
Work
metody jest rzutowane na obiekt. Oznacza to, że w ramachWork
metody należy ponownie rzutować na oryginalny typ, jak w poniższym przykładzie:Przesyłanie jest czymś, czego zwykle nie chcesz robić.
Co się stanie, jeśli ktoś przekaże coś innego, co nie jest łańcuchem? Ponieważ na początku wydaje się to niemożliwe (ponieważ jest to moja metoda, wiem, co robię lub metoda ta jest prywatna, w jaki sposób ktoś powinien być w stanie przekazać coś do niej? ), Być może z tego powodu możesz skończyć dokładnie z tą sprawą . Ponieważ niektóre przypadki mogą nie stanowić problemu, inne tak. W takich przypadkach prawdopodobnie skończysz z
InvalidCastException
czymś, czego prawdopodobnie nie zauważysz, ponieważ po prostu kończy wątek.Jako rozwiązanie można oczekiwać ogólnego
ParameterizedThreadStart
delegata, na przykład,ParameterizedThreadStart<T>
gdzieT
byłby typ danych, które chcesz przekazać doWork
metody. Niestety coś takiego jeszcze nie istnieje (jeszcze?).Istnieje jednak sugerowane rozwiązanie tego problemu. Polega ona na utworzeniu klasy, która zawiera zarówno dane, które mają być przekazywane do wątku, jak i metodę reprezentującą metodę roboczą w następujący sposób:
Przy takim podejściu zaczynasz wątek w następujący sposób:
W ten sposób po prostu unikniesz przerzucania się i masz bezpieczny sposób dostarczania danych do wątku ;-)
źródło
private static void MyMethod<T>(T myData) { T message = myData; Console.WriteLine($"the thread wrote: {message}"); }
message.Length
nie jest możliwe itd.)if(myData.GetType() == typeof(string)) { var str = ((string)(object)myData).Length; }
. W każdym razie zamiast korzystania z metody wątkowania uznałem, że jest to bardziej wygodne w użyciuTasks<T>
, na przykładtasks.Add(Task.Run(() => Calculate(par1, par2, par3)))
zobacz moją odpowiedź poniżej ( stackoverflow.com/a/59777250/7586301 )Miałem problem z przekazanym parametrem. Przekazałem do funkcji liczbę całkowitą z pętli for i wyświetliłem ją, ale zawsze dawała inne wyniki. jak (1,2,2,3) (1,2,3,3) (1,1,2,3) itd. z delegatem ParametrizedThreadStart .
ten prosty kod działał jako urok
źródło
ParameterizedThreadStart
Pobiera jeden parametr. Możesz użyć tego do wysłania jednego parametru lub niestandardowej klasy zawierającej kilka właściwości.Inną metodą jest umieszczenie metody, którą chcesz uruchomić jako element instancji w klasie, wraz z właściwościami parametrów, które chcesz ustawić. Utwórz instancję klasy, ustaw właściwości i uruchom wątek, określając instancję i metodę, a metoda może uzyskać dostęp do właściwości.
źródło
Możesz użyć delegata ParametrizedThreadStart :
źródło
Możesz użyć metody RunWorkerAsync BackgroundWorker i przekazać swoją wartość.
źródło
źródło
Proponuję używać
Task<T>
zamiastThread
; pozwala na wiele parametrów i działa naprawdę dobrze.Oto działający przykład:
źródło
źródło