webentwicklung-frage-antwort-db.com.de

ThreadStart mit Parametern

Wie startet man einen Thread mit Parametern in C #?

240
JL.

Ja:

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

Bei einer der beiden Überladungen des Thread-Konstruktors wird ein ParameterizedThreadStart-Delegat verwendet, mit dem Sie einen einzelnen Parameter an die start-Methode übergeben können. Leider ist nur ein einziger Parameter zulässig, und das auf unsichere Weise, da er als Objekt übergeben wird. Ich finde es viel einfacher, mit einem Lambda-Ausdruck die relevanten Parameter zu erfassen und stark typisiert zu übergeben.

Versuche Folgendes

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

Sie können Lambda-Ausdrücke verwenden

private void MyMethod(string param1,int param2)
{
  //do stuff
}
Thread myNewThread = new Thread(() => MyMethod("param1",5));
myNewThread.Start();

dies ist bis jetzt die beste Antwort, die ich finden konnte. Es ist schnell und einfach.

126
Georgi-it
Thread thread = new Thread(Work);
thread.Start(Parameter);

private void Work(object param)
{
    string Parameter = (string)param;
}

Der Parametertyp muss ein Objekt sein.

EDIT:

Während diese Antwort nicht falsch ist, empfehle ich gegen diesen Ansatz. Die Verwendung eines Lambda-Ausdrucks ist viel einfacher zu lesen und erfordert keine Typumwandlung. Siehe hier: 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

Einfacher Weg mit Lambda wie so ..

Thread t = new Thread(() => DoSomething("param1", "param2"));
t.Start();

ODER Sie könnten sogar delegate mit ThreadStart wie folgt verwenden ...

ThreadStart ts = delegate
{
     bool moreWork = DoWork("param1", "param2", "param3");
     if (moreWork) 
     {
          DoMoreWork("param1", "param2");
     }
};
new Thread(ts).Start();
23
Master Mick

Verwenden Sie ParameterizedThreadStart .

8
Justin Niessner

Verwenden Sie ParametrizedThreadStart .

8
Thomas

Ich hatte ein Problem mit dem übergebenen Parameter. Ich habe eine Ganzzahl von einer for-Schleife an die Funktion übergeben und sie angezeigt, aber es wurden immer unterschiedliche Ergebnisse ausgegeben. wie (1,2,2,3) (1,2,3,3) (1,1,2,3) usw. mit ParametrizedThreadStart delegieren.

dieser einfache Code wirkte wie ein Zauber

Thread thread = new Thread(Work);
thread.Start(Parameter);

private void Work(object param) 
{
 string Parameter = (string)param; 
}
5
user3805007

Das ParameterizedThreadStart akzeptiert einen Parameter. Damit können Sie einen Parameter oder eine benutzerdefinierte Klasse mit mehreren Eigenschaften senden.

Eine andere Methode besteht darin, die Methode, die Sie als Instanzmitglied starten möchten, zusammen mit den Eigenschaften für die Parameter, die Sie festlegen möchten, in eine Klasse einzufügen. Erstellen Sie eine Instanz der Klasse, legen Sie die Eigenschaften fest und starten Sie den Thread, indem Sie die Instanz und die Methode angeben. Die Methode kann dann auf die Eigenschaften zugreifen.

4
Guffa

Sie könnten einen ParametrizedThreadStart Delegaten verwenden:

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

Sie können die Methode BackgroundWorkerRunWorkerAsync verwenden und Ihren Wert übergeben.

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`
    }
}

Wie bereits in verschiedenen Antworten erwähnt, bietet die Klasse Thread aktuell (4.7.2) mehrere Konstruktoren und ein Start Methode mit Überladungen.

Diese relevanten Konstruktoren für diese Frage sind:

public Thread(ThreadStart start);

und

public Thread(ParameterizedThreadStart start);

die entweder einen ThreadStart Delegierten oder einen ParameterizedThreadStart Delegierten aufnehmen.

Die entsprechenden Delegierten sehen folgendermaßen aus:

public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);

Wie zu sehen ist, scheint der richtige Konstruktor derjenige zu sein, der einen ParameterizedThreadStart -Delegaten entgegennimmt, so dass eine Methode, die der angegebenen Signatur des Delegaten entspricht, vom Thread gestartet werden kann.

Ein einfaches Beispiel für die Instanziierung der Klasse Thread wäre

Thread thread = new Thread(new ParameterizedThreadStart(Work));

oder nur

Thread thread = new Thread(Work);

Die Signatur der entsprechenden Methode (in diesem Beispiel Work genannt) sieht folgendermaßen aus:

private void Work(object data)
{
   ...
}

Was bleibt ist, den Thread zu starten. Dies geschieht entweder mit

public void Start();

oder

public void Start(object parameter);

Während Start() den Thread starten und null als Daten an die Methode übergeben würde, kann Start(...) verwendet werden, um alles an die Methode zu übergeben Work Methode des Threads.

Es gibt jedoch ein großes Problem bei diesem Ansatz: Alles, was an die Work -Methode übergeben wird, wird in ein Objekt umgewandelt. Das bedeutet, dass innerhalb der Work -Methode erneut auf den ursprünglichen Typ umgewandelt werden muss, wie im folgenden Beispiel gezeigt:

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}");
}



Casting ist etwas, das Sie normalerweise nicht möchten.

Was ist, wenn jemand etwas anderes übergibt, das keine Schnur ist? Da dies zunächst nicht möglich zu sein scheint (weil Es ist meine Methode, ich weiß was ich tue oder Die Methode ist privat, wie sollte jemand jemals in der Lage sein, etwas an sie weiterzugeben? ) Möglicherweise haben Sie aus verschiedenen Gründen genau diesen Fall. Da einige Fälle möglicherweise kein Problem darstellen, sind es andere. In solchen Fällen erhalten Sie wahrscheinlich ein InvalidCastException , das Sie wahrscheinlich nicht bemerken werden, weil es den Thread einfach beendet.

Als Lösung würden Sie einen generischen ParameterizedThreadStart -Delegaten wie ParameterizedThreadStart<T> Erwarten, wobei T der Datentyp ist, den Sie an die Work -Methode übergeben möchten . Leider existiert so etwas (noch?) Nicht.

Es gibt jedoch ein Lösungsvorschlag für dieses Problem. Es wird eine Klasse erstellt, die sowohl die an den Thread zu übergebenden Daten als auch die Methode enthält, die die Worker-Methode wie folgt darstellt:

public class ThreadWithState
{
    private string message;

    public ThreadWithState(string message)
    {
        this.message = message;
    }

    public void Work()
    {
        Console.WriteLine($"I, the thread write: {this.message}");
    }
}

Mit diesem Ansatz würden Sie den Thread wie folgt starten:

ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);

thread.Start();

Auf diese Weise vermeiden Sie einfach das Herumwerfen und haben eine typsichere Möglichkeit, Daten für einen Thread bereitzustellen ;-)

0
Markus Safar