Comment commencez-vous un fil avec des paramètres en C #?
Oui
Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);
L'une des 2 surcharges du constructeur Thread prend un délégué ParameterizedThreadStart qui vous permet de transmettre un seul paramètre à la méthode start. Malheureusement, il ne permet qu'un seul paramètre et le fait d'une manière non sécurisée, car il le transmet en tant qu'objet. Je trouve qu'il est beaucoup plus facile d'utiliser une expression lambda pour capturer les paramètres pertinents et les transmettre de manière très typée.
Essayez ce qui suit
public Thread StartTheThread(SomeType param1, SomeOtherType param2) {
var t = new Thread(() => RealStart(param1, param2));
t.Start();
return t;
}
private static void RealStart(SomeType param1, SomeOtherType param2) {
...
}
Vous pouvez utiliser des expressions lambda
private void MyMethod(string param1,int param2)
{
//do stuff
}
Thread myNewThread = new Thread(() => MyMethod("param1",5));
myNewThread.Start();
c’est la meilleure réponse que j’ai pu trouver jusqu’à présent, c’est rapide et facile.
Thread thread = new Thread(Work);
thread.Start(Parameter);
private void Work(object param)
{
string Parameter = (string)param;
}
Le type de paramètre doit être un objet.
EDIT:
Bien que cette réponse ne soit pas incorrecte, je recommande cette approche. L'utilisation d'une expression lambda est beaucoup plus facile à lire et ne nécessite pas de transtypage. Voir ici: https://stackoverflow.com/a/1195915/52551
class Program
{
static void Main(string[] args)
{
Thread t = new Thread(new ParameterizedThreadStart(ThreadMethod));
t.Start("My Parameter");
}
static void ThreadMethod(object parameter)
{
// parameter equals to "My Parameter"
}
}
Manière simple en utilisant lambda comme si ..
Thread t = new Thread(() => DoSomething("param1", "param2"));
t.Start();
OU vous pourriez même delegate
utiliser ThreadStart
comme si ...
ThreadStart ts = delegate
{
bool moreWork = DoWork("param1", "param2", "param3");
if (moreWork)
{
DoMoreWork("param1", "param2");
}
};
new Thread(ts).Start();
Utilisez ParameterizedThreadStart .
Utilisez ParametrizedThreadStart
.
J'avais problème dans le paramètre passé. J'ai passé l'entier d'une boucle for à la fonction et l'a affiché, mais il a toujours donné des résultats différents. comme (1,2,2,3) (1,2,3,3) (1,1,2,3) etc. avec ParametrizedThreadStart délégué.
ce code simple a fonctionné comme un charme
Thread thread = new Thread(Work);
thread.Start(Parameter);
private void Work(object param)
{
string Parameter = (string)param;
}
La ParameterizedThreadStart
prend un paramètre. Vous pouvez l'utiliser pour envoyer un paramètre ou une classe personnalisée contenant plusieurs propriétés.
Une autre méthode consiste à placer la méthode que vous souhaitez démarrer en tant que membre d'instance dans une classe avec les propriétés des paramètres que vous souhaitez définir. Créez une instance de la classe, définissez les propriétés et démarrez le fil en spécifiant l'instance et la méthode. La méthode peut accéder aux propriétés.
Vous pouvez utiliser un ParametrizedThreadStart délégué:
string parameter = "Hello world!";
Thread t = new Thread(new ParameterizedThreadStart(MyMethod));
t.Start(parameter);
Vous pouvez utiliser la méthode BackgroundWorkerRunWorkerAsync et transmettre votre valeur.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApp6
{
class Program
{
static void Main(string[] args)
{
int x = 10;
Thread t1 =new Thread(new ParameterizedThreadStart(order1));
t1.IsBackground = true;//i can stope
t1.Start(x);
Thread t2=new Thread(order2);
t2.Priority = ThreadPriority.Highest;
t2.Start();
Console.ReadKey();
}//Main
static void order1(object args)
{
int x = (int)args;
for (int i = 0; i < x; i++)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(i.ToString() + " ");
}
}
static void order2()
{
for (int i = 100; i > 0; i--)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(i.ToString() + " ");
}
}`enter code here`
}
}
Comme cela a déjà été mentionné dans diverses réponses, la classe Thread
(4.7.2) fournit plusieurs constructeurs et une méthode Start
avec surcharges.
Ces constructeurs pertinents pour cette question sont:
public Thread(ThreadStart start);
et
public Thread(ParameterizedThreadStart start);
qui soit prend un ThreadStart
délégué ou un ParameterizedThreadStart
.
Les délégués correspondants ressemblent à ceci:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
Donc, comme on peut le constater, le constructeur approprié à utiliser semble être celui prenant un délégué ParameterizedThreadStart
de sorte 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 classe Thread
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 commencer le fil. Ceci est fait en utilisant soit
public void Start();
ou
public void Start(object parameter);
Tandis que Start()
démarrerait le thread et transmettrait null
en tant que données à la méthode, Start(...)
peut être utilisé pour passer n'importe quoi dans la méthode Work
du thread.
Il existe toutefois un gros problème avec cette approche: tout ce qui est passé dans la méthode Work
est converti en un objet. Cela signifie que dans la méthode Work
, il doit être converti dans le type d'origine à nouveau, 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 une 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 semble impossible au début (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 ), vous pouvez éventuellement vous retrouver exactement dans cette affaire pour diverses raisons. Comme certains cas peuvent ne pas être un problème, d'autres le sont. Dans de tels cas, vous obtiendrez probablement un InvalidCastException
que vous ne remarquerez probablement pas, car il met simplement fin au fil.
En tant que solution, vous devriez vous attendre à obtenir un délégué générique ParameterizedThreadStart
tel que ParameterizedThreadStart<T>
où T
serait le type de données que vous souhaitez transmettre à la méthode Work
. Malheureusement, quelque chose comme ça n'existe pas (encore?).
Il existe cependant une solution suggérée à cette question. Cela implique la création d'une classe qui contient à la fois les données à transmettre au thread et la méthode qui représente la méthode de travail de la manière suivante:
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 des discussions et vous avez un moyen sûr de fournir des données à un thread ;-)