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 Threadclasse actuellement (4.7.2) fournit plusieurs constructeurs et une Startméthode avec des surcharges.
Ces constructeurs pertinents pour cette question sont:
public Thread(ThreadStart start);
et
public Thread(ParameterizedThreadStart start);
qui soit prendre un ThreadStartdélégué ou un ParameterizedThreadStartdé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 ParameterizedThreadStartdé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 Threadclasse serait
Thread thread = new Thread(new ParameterizedThreadStart(Work));
ou juste
Thread thread = new Thread(Work);
La signature de la méthode correspondante (appelée Workdans 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 nullcomme 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 Workméthode est converti en objet. Cela signifie que dans la Workmé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 ParameterizedThreadStartdé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 ;-)