Selon votre question ...
Comment passer des paramètres à la méthode Thread.ThreadStart () en C #?
... et l'erreur que vous avez rencontrée, vous devrez corriger votre code à partir de
Thread thread = new Thread(new ThreadStart(download(filename));
à
Thread thread = new Thread(new ThreadStart(download));
thread.Start(filename);
Cependant, la question est plus complexe qu'elle semble au premier abord.
La Thread
classe actuellement (4.7.2) fournit plusieurs constructeurs et une Start
méthode avec des surcharges.
Ces constructeurs pertinents pour cette question sont:
public Thread(ThreadStart start);
et
public Thread(ParameterizedThreadStart start);
qui soit prendre un ThreadStart
délégué ou un ParameterizedThreadStart
délégué.
Les délégués correspondants ressemblent à ceci:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
Ainsi, comme on peut le voir, le constructeur correct à utiliser semble être celui qui prend un ParameterizedThreadStart
délégué afin qu'une certaine méthode conforme à la signature spécifiée du délégué puisse être démarrée par le thread.
Un exemple simple d'instanciation de la Thread
classe serait
Thread thread = new Thread(new ParameterizedThreadStart(Work));
ou juste
Thread thread = new Thread(Work);
La signature de la méthode correspondante (appelée Work
dans cet exemple) ressemble à ceci:
private void Work(object data)
{
...
}
Ce qui reste est de démarrer le fil. Cela se fait en utilisant soit
public void Start();
ou
public void Start(object parameter);
Alors Start()
que démarrerait le thread et passerait null
comme données à la méthode, Start(...)
peut être utilisé pour passer n'importe quoi dans leWork
méthode du thread.
Il y a cependant un gros problème avec cette approche: tout ce qui est passé dans la Work
méthode est converti en objet. Cela signifie que dans la Work
méthode, il doit à nouveau être converti en type d'origine, comme dans l'exemple suivant:
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}");
}
Le casting est quelque chose que vous ne voulez généralement pas faire.
Et si quelqu'un passe quelque chose d'autre qui n'est pas une chaîne? Comme cela ne semble pas possible au premier abord (parce que c'est ma méthode, je sais ce que je fais ou la méthode est privée, comment quelqu'un devrait-il pouvoir lui transmettre quoi que ce soit? ), Vous pouvez éventuellement vous retrouver exactement avec ce cas pour diverses raisons . Comme certains cas peuvent ne pas être un problème, d'autres le sont. Dans de tels cas, vous vous retrouverez probablement avec unInvalidCastException
que vous ne remarquerez probablement pas car il termine simplement le thread.
Comme solution, vous vous attendez à obtenir un ParameterizedThreadStart
délégué générique comme ParameterizedThreadStart<T>
oùT
serait le type de données que vous souhaitez transmettre dans leWork
méthode. Malheureusement, quelque chose comme ça n'existe pas (encore?).
Il existe cependant une solution suggérée à ce problème. Cela implique de créer une classe qui contient les deux, les données à transmettre au thread ainsi que la méthode qui représente la méthode de travail comme ceci:
public class ThreadWithState
{
private string message;
public ThreadWithState(string message)
{
this.message = message;
}
public void Work()
{
Console.WriteLine($"I, the thread write: {this.message}");
}
}
Avec cette approche, vous commenceriez le fil comme ceci:
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
Donc, de cette façon, vous évitez simplement de lancer et d'avoir un moyen sûr de fournir des données à un thread ;-)