Nach Ihrer Frage ...
Wie übergebe ich Parameter an die Thread.ThreadStart () -Methode in C #?
... und den Fehler, auf den Sie gestoßen sind, müssten Sie Ihren Code von korrigieren
Thread thread = new Thread(new ThreadStart(download(filename));
zu
Thread thread = new Thread(new ThreadStart(download));
thread.Start(filename);
Die Frage ist jedoch komplexer, wie es zunächst scheint.
Die ThreadKlasse (4.7.2) bietet derzeit mehrere Konstruktoren und eine StartMethode mit Überladungen.
Diese relevanten Konstruktoren für diese Frage sind:
public Thread(ThreadStart start);
und
public Thread(ParameterizedThreadStart start);
die entweder einen ThreadStartDelegierten oder einen ParameterizedThreadStartDelegierten nehmen.
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 ParameterizedThreadStartDelegaten nimmt, so dass eine Methode, die der angegebenen Signatur des Delegaten entspricht, vom Thread gestartet werden kann.
Ein einfaches Beispiel für die Instanziierung der ThreadKlasse wäre
Thread thread = new Thread(new ParameterizedThreadStart(Work));
oder nur
Thread thread = new Thread(Work);
Die Signatur der entsprechenden Methode ( Workin diesem Beispiel aufgerufen ) sieht folgendermaßen aus:
private void Work(object data)
{
...
}
Was bleibt, ist den Thread zu starten. Dies erfolgt entweder mit
public void Start();
oder
public void Start(object parameter);
Während Start()der Thread gestartet und nullals Daten an die Methode übergeben würde, Start(...)kann verwendet werden, um alles an die WorkMethode des Threads zu übergeben.
Bei diesem Ansatz gibt es jedoch ein großes Problem: Alles, was an die WorkMethode übergeben wird, wird in ein Objekt umgewandelt. Das heißt, innerhalb der WorkMethode muss es wieder wie im folgenden Beispiel in den ursprünglichen Typ umgewandelt werden:
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, was Sie normalerweise nicht wollen.
Was ist, wenn jemand etwas anderes übergibt, das keine Zeichenfolge ist? Da dies zunächst nicht möglich zu sein scheint (weil es meine Methode ist, ich weiß, was ich tue oder die Methode privat ist, wie sollte jemand jemals etwas an sie weitergeben können? ), Können Sie möglicherweise aus verschiedenen Gründen genau diesen Fall haben . Da einige Fälle möglicherweise kein Problem darstellen, sind es andere. In solchen Fällen werden Sie wahrscheinlich mit einem endenInvalidCastException die Sie wahrscheinlich nicht bemerken werden, weil sie den Thread einfach beendet.
Als Lösung würden erwarten , dass Sie ein generisch erhalten ParameterizedThreadStartDelegierten wie , ParameterizedThreadStart<T>wo Tdie Daten der Typ , der Sie in denen geben wollen wäre WorkMethode. Leider gibt es so etwas (noch?) Nicht.
Es gibt jedoch eine vorgeschlagene Lösung für dieses Problem. Dabei wird eine Klasse erstellt, die sowohl die an den Thread zu übergebenden Daten als auch die Methode enthält, die die Arbeitsmethode 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 folgendermaßen 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 Herumwirbeln und haben eine typsichere Möglichkeit, Daten für einen Thread bereitzustellen ;-)