web-dev-qa-db-fra.com

ThreadStart avec des paramètres

Comment commencez-vous un fil avec des paramètres en C #?

240
JL.

Oui

Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);
158
Erick

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) {
  ...
}
452
JaredPar

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.

126
Georgi-it
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

34
Spencer Ruport
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"
    }
}
29
huseyint

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();
23
Master Mick
8
Justin Niessner
8
Thomas

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; 
}
5
user3805007

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.

4
Guffa

Vous pouvez utiliser un ParametrizedThreadStart délégué:

string parameter = "Hello world!";
Thread t = new Thread(new ParameterizedThreadStart(MyMethod));
t.Start(parameter);
3
CMS

Vous pouvez utiliser la méthode BackgroundWorkerRunWorkerAsync et transmettre votre valeur.

3
SwDevMan81
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>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 ;-)

0
Markus Safar