Jak przekazać parametry do Thread.ThreadStart()
metody w C #?
Załóżmy, że mam metodę o nazwie „pobierz”
public void download(string filename)
{
// download code
}
Teraz utworzyłem jeden wątek w metodzie głównej:
Thread thread = new Thread(new ThreadStart(download(filename));
oczekiwany typ błędu.
Jak mogę przekazać parametry za ThreadStart
pomocą metody docelowej z parametrami?
c#
.net
multithreading
Swapnil Gupta
źródło
źródło
Odpowiedzi:
Najprostsze jest po prostu
Zaletą tego (ponad
ParameterizedThreadStart
) jest to, że można przekazać wiele parametrów i uzyskać sprawdzanie czasu kompilacji bez konieczności ciągłego rzutowaniaobject
.źródło
new Thread(delegate() { download(filename); });
Spójrz na ten przykład:
Najpierw tworzysz wątek, przekazując delegata do metody pracownika, a następnie uruchamiasz go za pomocą metody Thread.Start, która przyjmuje obiekt jako parametr.
Więc w twoim przypadku powinieneś użyć go w ten sposób:
Ale twoja metoda „pobierania” nadal musi przyjmować obiekt , a nie ciąg znaków jako parametr. Możesz rzucić go na ciąg znaków w treści metody.
źródło
Chcesz użyć
ParameterizedThreadStart
delegata do metod wątków, które pobierają parametry. (Lub w ogóle żaden, i pozwólThread
konstruktorowi wnioskować.)Przykładowe użycie:
źródło
Może ci się też
delegate
spodobać ...źródło
W dodatkowej
źródło
Możesz obudować funkcję wątku (pobieranie) i potrzebne parametry (nazwę pliku) w klasie i użyć delegata ThreadStart do wykonania funkcji wątku.
źródło
Poleciłbym ci inną klasę o nazwie File.
W kodzie tworzenia wątków tworzysz nowy plik:
źródło
Co powiesz na to: (czy można używać w ten sposób?)
źródło
Zgodnie z twoim pytaniem ...
... i napotkany błąd, musisz poprawić swój kod
do
Pytanie to jest jednak bardziej złożone, jak się wydaje na początku.
Obecnie
Thread
klasa (4.7.2) udostępnia 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
oto idealny sposób ...
źródło