Selon votre question...
Comment passer des paramètres à la méthode Thread.ThreadStart() en C# ?
...et l'erreur que vous avez rencontrée, vous devriez 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'il n'y paraît au premier abord.
En Thread
Actuellement, la classe (4.7.2) fournit plusieurs fonctions de constructeurs et un Start
avec des surcharges.
Ces constructeurs pertinents pour cette question sont :
public Thread(ThreadStart start);
y
public Thread(ParameterizedThreadStart start);
qui prennent soit un ThreadStart
ou un délégué 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 une valeur de ParameterizedThreadStart
afin qu'une méthode conforme à la signature spécifiée du délégué puisse être lancée par le thread.
Un exemple simple d'instanciation de la Thread
La classe serait
Thread thread = new Thread(new ParameterizedThreadStart(Work));
ou simplement
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)
{
...
}
Il ne reste plus qu'à lancer le fil. Cela se fait en utilisant soit
public void Start();
ou
public void Start(object parameter);
Alors que Start()
commencerait le fil et passerait null
comme données pour la méthode, Start(...)
peut être utilisé pour passer tout ce qui est dans le Work
du fil.
Il y a cependant un gros problème avec cette approche : Tout ce qui est passé dans le Work
est transformée en objet. Cela signifie qu'au sein de la méthode Work
il doit être remis dans le type original 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 moulage est une chose que vous ne voulez généralement pas faire.
Que se passe-t-il si quelqu'un passe quelque chose d'autre qui n'est pas une chaîne ? Comme cela ne semble pas possible au départ (parce que C'est ma méthode, je sais ce que je fais. o La méthode est privée, comment quelqu'un pourrait-il lui passer quelque chose ? ), vous pouvez éventuellement vous retrouver dans ce cas précis pour diverses raisons. Si certains cas ne posent pas de problème, d'autres en posent. Dans ces cas-là, vous vous retrouverez probablement avec un fichier InvalidCastException
que vous ne remarquerez probablement pas, car il met simplement fin au fil.
En guise de solution, on s'attendrait à obtenir un générique ParameterizedThreadStart
délégué comme ParameterizedThreadStart<T>
donde T
serait le type de données que vous voulez passer dans la fonction Work
méthode. Malheureusement, une telle méthode n'existe pas (encore ?).
Il existe cependant un solution proposée à cette question. Il s'agit de créer une classe qui contient à la fois les données à transmettre au thread et la méthode qui représente la méthode du travailleur, 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 commencerez le fil de discussion comme ceci :
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
De cette façon, vous évitez simplement le casting et disposez d'un moyen sûr de fournir des données à un thread ;-)
3 votes
Vérifiez ce article écrit par Jon Skeet La section sur les paramètres se trouve à la page suivante, mais l'article dans son ensemble est plutôt intéressant à lire.