De acuerdo a tu pregunta ...
¿Cómo pasar parámetros al método Thread.ThreadStart () en C #?
... y el error que encontró, tendría que corregir su código de
Thread thread = new Thread(new ThreadStart(download(filename));
a
Thread thread = new Thread(new ThreadStart(download));
thread.Start(filename);
Sin embargo, la pregunta es más compleja como parece al principio.
La Thread
clase actualmente (4.7.2) proporciona varios constructores y un Start
método con sobrecargas.
Estos constructores relevantes para esta pregunta son:
public Thread(ThreadStart start);
y
public Thread(ParameterizedThreadStart start);
que o bien toman un ThreadStart
delegado o un ParameterizedThreadStart
delegado.
Los delegados correspondientes se ven así:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
Como se puede ver, el constructor correcto para usar parece ser el que toma un ParameterizedThreadStart
delegado para que el hilo pueda iniciar algún método conforme a la firma especificada del delegado.
Un ejemplo simple para instanciar la Thread
clase sería
Thread thread = new Thread(new ParameterizedThreadStart(Work));
o solo
Thread thread = new Thread(Work);
La firma del método correspondiente (llamado Work
en este ejemplo) se ve así:
private void Work(object data)
{
...
}
Lo que queda es comenzar el hilo. Esto se hace usando cualquiera
public void Start();
o
public void Start(object parameter);
Si bien Start()
iniciaría el hilo y pasaría null
como datos al método, Start(...)
se puede usar para pasar cualquier cosa al Work
método del hilo.
Sin embargo, hay un gran problema con este enfoque: todo lo que se pasa al Work
método se convierte en un objeto. Eso significa que dentro del Work
método tiene que volver al tipo original, como en el siguiente ejemplo:
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}");
}
El casting es algo que normalmente no quieres hacer.
¿Qué pasa si alguien pasa algo más que no es una cadena? Como parece que esto no es posible al principio (porque es mi método, sé lo que hago o el método es privado, ¿cómo debería alguien ser capaz de pasarle algo? ) Es posible que termine exactamente con ese caso por varias razones . Como algunos casos pueden no ser un problema, otros sí lo son. En tales casos, probablemente terminará con uno InvalidCastException
que probablemente no notará porque simplemente termina el hilo.
Como solución, esperaría obtener un ParameterizedThreadStart
delegado genérico como ParameterizedThreadStart<T>
dónde T
sería el tipo de datos que desea pasar al Work
método. Lamentablemente, algo como esto no existe (¿todavía?).
Sin embargo, hay una solución sugerida para este problema. Implica crear una clase que contenga ambos, los datos que se pasarán al subproceso y el método que representa el método de trabajo de esta manera:
public class ThreadWithState
{
private string message;
public ThreadWithState(string message)
{
this.message = message;
}
public void Work()
{
Console.WriteLine($"I, the thread write: {this.message}");
}
}
Con este enfoque, comenzaría el hilo de esta manera:
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
De esta manera, simplemente evitas dar vueltas y tienes una forma segura de proporcionar datos a un hilo ;-)