Secondo la tua domanda ...
Come passare i parametri al metodo Thread.ThreadStart () in C #?
... e l'errore che hai riscontrato, dovresti correggere il tuo codice
Thread thread = new Thread(new ThreadStart(download(filename));
per
Thread thread = new Thread(new ThreadStart(download));
thread.Start(filename);
Tuttavia, la domanda è più complessa come sembra all'inizio.
La Thread
classe attualmente (4.7.2) fornisce diversi costruttori e un Start
metodo con sovraccarichi.
Questi costruttori rilevanti per questa domanda sono:
public Thread(ThreadStart start);
e
public Thread(ParameterizedThreadStart start);
che può assumere un ThreadStart
delegato o un ParameterizedThreadStart
delegato.
I delegati corrispondenti si presentano così:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
Come si può vedere, il costruttore corretto da usare sembra essere quello che prende un ParameterizedThreadStart
delegato in modo che un thread conforme alla firma specificata del delegato possa essere avviato dal thread.
Un semplice esempio per istanziare la Thread
classe sarebbe
Thread thread = new Thread(new ParameterizedThreadStart(Work));
o solo
Thread thread = new Thread(Work);
La firma del metodo corrispondente (chiamato Work
in questo esempio) è simile alla seguente:
private void Work(object data)
{
...
}
Ciò che resta è iniziare il thread. Questo viene fatto usando uno dei due
public void Start();
o
public void Start(object parameter);
Mentre Start()
avviare il thread e passare null
come dati al metodo, Start(...)
può essere utilizzato per passare qualsiasi cosa nel Work
metodo del thread.
Esiste tuttavia un grosso problema con questo approccio: tutto ciò che viene passato nel Work
metodo viene trasmesso in un oggetto. Ciò significa che all'interno del Work
metodo deve essere nuovamente eseguito il cast nel tipo originale come nell'esempio seguente:
public static void Main(string[] args)
{
Thread thread = new Thread(Work);
thread.Start("I've got some text");
Console.ReadLine();
}
private static void Work(object data)
{
string message = (string)data; // Wow, this is ugly
Console.WriteLine($"I, the thread write: {message}");
}
Il casting è qualcosa che in genere non si desidera fare.
Cosa succede se qualcuno passa qualcos'altro che non è una stringa? Dal momento che questo non sembra possibile all'inizio (poiché è il mio metodo, so cosa faccio o Il metodo è privato, come dovrebbe mai qualcuno essere in grado di passargli qualcosa? ), Potresti finire con quel caso per vari motivi . Poiché alcuni casi potrebbero non essere un problema, altri lo sono. In questi casi probabilmente finirai con unInvalidCastException
che probabilmente non noterai perché termina semplicemente il thread.
Come soluzione ti aspetteresti di ottenere un ParameterizedThreadStart
delegato generico come ParameterizedThreadStart<T>
dove T
sarebbe il tipo di dati che vuoi passare al Work
metodo. Purtroppo qualcosa del genere non esiste (ancora?).
Esiste tuttavia una soluzione suggerita a questo problema. Implica la creazione di una classe che contenga sia i dati da passare al thread sia il metodo che rappresenta il metodo worker in questo modo:
public class ThreadWithState
{
private string message;
public ThreadWithState(string message)
{
this.message = message;
}
public void Work()
{
Console.WriteLine($"I, the thread write: {this.message}");
}
}
Con questo approccio inizieresti il thread in questo modo:
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
Quindi in questo modo eviti semplicemente di lanciarti e hai un modo semplice di fornire dati a un thread ;-)