La respuesta a esta pregunta varía ampliamente entre las versiones del tiempo de ejecución.
Quillbreaker
44
Guau. He estado editando algunas de tus preguntas anteriores, pero podría ser un trabajo de tiempo completo. Olvidé cuánto has mejorado con los años. :-)
John Saunders
Si hiciera una pregunta tan breve, obtendría 5 puntuaciones negativas o incluso más. Aunque la pregunta y la respuesta me ayudaron.
Mohammad Musavi
Respuestas:
174
Sí:
Thread t =newThread(newParameterizedThreadStart(myMethod));
t.Start(myParameterObject);
es esto lo mismo: ThreadStart processTaskThread = delegate {ProcessTasks (databox.DataboxID); }; nuevo hilo (processTaskThread) .Start ();
JL.
43
¿Qué es myParamObject y myUrl?
dialex
3
En este caso void MyParamObject(object myUrl){ //do stuff }debería tener el tipo de parámetroobject
Elshan
15
-1 porque la respuesta supone que el OP sabe cómo usar ParameterizedThreadStarty claramente del texto de la pregunta, probablemente ese no sea el caso.
JYelton
2
Tengo este error Error CS0123 Ninguna sobrecarga para 'UpdateDB' coincide con el delegado 'ParameterizedThreadStart'
Omid Farvid
482
Una de las 2 sobrecargas del constructor Thread toma un delegado ParameterizedThreadStart que le permite pasar un solo parámetro al método de inicio. Desafortunadamente, solo permite un único parámetro y lo hace de manera insegura porque lo pasa como objeto. Encuentro que es mucho más fácil usar una expresión lambda para capturar los parámetros relevantes y pasarlos de manera fuertemente tipada.
Intenta lo siguiente
publicThreadStartTheThread(SomeType param1,SomeOtherType param2){var t =newThread(()=>RealStart(param1, param2));
t.Start();return t;}privatestaticvoidRealStart(SomeType param1,SomeOtherType param2){...}
+1: Aunque la respuesta seleccionada actualmente es absolutamente correcta, esta de JaredPar es la mejor. Simplemente es la mejor solución para la mayoría de los casos prácticos.
galaktor
2
Esta solución es mucho mejor que el punto de vista ParameterizedThreadStart
Piotr Owsiak
55
Agradable, muy simple. Simplemente envuelva cualquier llamada en "new Thread (() => FooBar ()) .Start ();
Thomas Jespersen
12
Impresionante, esto es para chicos de VB.NETDim thr As New Thread(Sub() DoStuff(settings))
dr. mal
3
@bavaza Me estaba refiriendo a la comprobación de tipos estáticos
Esto funcionó para mí. Probé el ParameterizedThreadStart y sus variaciones, pero no tuve alegría. Estaba usando .NET Framework 4 en una aplicación de consola supuestamente simple.
Daniel Hollinrake
Esto funciona mejor para las personas que están acostumbradas a este tipo de delegados. Puede ser difícil para los principiantes entender. Sin embargo, esto está limpio para los estándares de C #. La respuesta aceptada no funciona para mí y no tengo tiempo para averiguar por qué.
Si bien esta respuesta no es incorrecta, sí recomiendo este enfoque. Usar una expresión lambda es mucho más fácil de leer y no requiere conversión de tipo. Ver aquí: https://stackoverflow.com/a/1195915/52551
¿Por qué estás ayudando con un código que no se compila;) Parameter?
Sebastian Xawery Wiśniowiecki
32
classProgram{staticvoidMain(string[] args){Thread t =newThread(newParameterizedThreadStart(ThreadMethod));
t.Start("My Parameter");}staticvoidThreadMethod(object parameter){// parameter equals to "My Parameter"}}
Como ya se ha mencionado en varias respuestas aquí, la Threadclase actualmente (4.7.2) proporciona varios constructores y unStart método con sobrecargas.
Estos constructores relevantes para esta pregunta son:
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 Threadclase sería
La firma del método correspondiente (llamado Worken este ejemplo) se ve así:
privatevoidWork(object data){...}
Lo que queda es comenzar el hilo. Esto se hace usando cualquiera
publicvoidStart();
o
publicvoidStart(object parameter);
Si bien Start()iniciaría el hilo y pasaría nullcomo datos al método, Start(...)se puede usar para pasar cualquier cosa al Workmétodo del hilo.
Sin embargo, hay un gran problema con este enfoque: todo lo que se pasa al Workmétodo se convierte en un objeto. Eso significa que dentro del Workmétodo tiene que volver al tipo original, como en el siguiente ejemplo:
publicstaticvoidMain(string[] args){Thread thread =newThread(Work);
thread.Start("I've got some text");Console.ReadLine();}privatestaticvoidWork(object data){string message =(string)data;// Wow, this is uglyConsole.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 esto parece no 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 unInvalidCastException que probablemente no notará porque simplemente termina el hilo.
Como solución, esperaría obtener un genérico ParameterizedThreadStart delegado como ParameterizedThreadStart<T>dónde Tsería el tipo de datos que desea pasar al Workmétodo. Desafortunadamente, algo como esto no existe (¿todavía?).
Sin embargo, hay un solución sugerida para este problema. Implica crear una clase que contenga tanto los datos que se pasarán al subproceso como el método que representa el método de trabajo de esta manera:
publicclassThreadWithState{privatestring message;publicThreadWithState(string message){this.message = message;}publicvoidWork(){Console.WriteLine($"I, the thread write: {this.message}");}}
Con este enfoque, comenzaría el hilo de esta manera:
ThreadWithState tws =newThreadWithState("I've got some text");Thread thread =newThread(tws.Work);
thread.Start();
Por lo tanto, de esta forma, simplemente evitas dar vueltas y tienes una forma segura de proporcionar datos a un hilo ;-)
Wow, un voto negativo sin comentarios ... O mi respuesta es tan mala como el elenco o el lector no entendió lo que intenté señalar aquí ;-)
Markus Safar
1
Encontré su solución muy enlightnen, felicidades. Solo quería agregar que ya lo probé en Net. ¡Tenga en cuenta lo siguiente y trabaje sin tener que explicitar! :-) private static void MyMethod<T>(T myData) { T message = myData; Console.WriteLine($"the thread wrote: {message}"); }
Paul Efford
@PaulEfford Gracias ;-) Su solución parece bastante buena. Pero no tienes acceso para escribir información específica, ya que todavía estará encuadrada en un objeto, ¿verdad? (por ejemplo, message.Lengthno es posible, etc.)
Markus Safar
1
bien ... podría enviar un mensaje. GetType () y emitir si se requiere alguna propiedad específica como if(myData.GetType() == typeof(string)) { var str = ((string)(object)myData).Length; }. De todos modos, en lugar de usar su método de enhebrado, encontré un poco más cómodo de usar Tasks<T>, como por ejemplo tasks.Add(Task.Run(() => Calculate(par1, par2, par3))), vea mi respuesta a continuación ( stackoverflow.com/a/59777250/7586301 )
Paul Efford
5
Estaba teniendo problemas en el parámetro pasado. Pasé un entero de un bucle for a la función y lo visualicé, pero siempre daba resultados diferentes. como (1,2,2,3) (1,2,3,3) (1,1,2,3), etc. con ParametrizedThreadStart delegado .
los ParameterizedThreadStart toma un parámetro. Puede usar eso para enviar un parámetro o una clase personalizada que contenga varias propiedades.
Otro método es colocar el método que desea comenzar como miembro de la instancia en una clase junto con las propiedades de los parámetros que desea establecer. Cree una instancia de la clase, establezca las propiedades e inicie el hilo especificando la instancia y el método, y el método puede acceder a las propiedades.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApp6{classProgram{staticvoidMain(string[] args){int x =10;Thread t1 =newThread(newParameterizedThreadStart(order1));
t1.IsBackground=true;//i can stope
t1.Start(x);Thread t2=newThread(order2);
t2.Priority=ThreadPriority.Highest;
t2.Start();Console.ReadKey();}//Mainstaticvoid order1(object args){int x =(int)args;for(int i =0; i < x; i++){Console.ForegroundColor=ConsoleColor.Green;Console.Write(i.ToString()+" ");}}staticvoid order2(){for(int i =100; i >0; i--){Console.ForegroundColor=ConsoleColor.Red;Console.Write(i.ToString()+" ");}}`enter code here`}}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApp6{classProgram{staticvoidMain(string[] args){int x =10;Thread t1 =newThread(newParameterizedThreadStart(order1));
t1.Start(x);Thread t2=newThread(order2);
t2.Priority=ThreadPriority.Highest;
t2.Start();Console.ReadKey();}//Mainstaticvoid order1(object args){int x =(int)args;for(int i =0; i < x; i++){Console.ForegroundColor=ConsoleColor.Green;Console.Write(i.ToString()+" ");}}staticvoid order2(){for(int i =100; i >0; i--){Console.ForegroundColor=ConsoleColor.Red;Console.Write(i.ToString()+" ");}}}}
El subprocesamiento múltiple con subprocesos C # le permite desarrollar aplicaciones más eficientes que se sincronizan a través de la memoria compartida.
Respuestas:
Sí:
fuente
void MyParamObject(object myUrl){ //do stuff }
debería tener el tipo de parámetroobject
ParameterizedThreadStart
y claramente del texto de la pregunta, probablemente ese no sea el caso.Una de las 2 sobrecargas del constructor Thread toma un delegado ParameterizedThreadStart que le permite pasar un solo parámetro al método de inicio. Desafortunadamente, solo permite un único parámetro y lo hace de manera insegura porque lo pasa como objeto. Encuentro que es mucho más fácil usar una expresión lambda para capturar los parámetros relevantes y pasarlos de manera fuertemente tipada.
Intenta lo siguiente
fuente
Dim thr As New Thread(Sub() DoStuff(settings))
Puedes usar expresiones lambda
Esta es hasta ahora la mejor respuesta que pude encontrar, es rápida y fácil.
fuente
El tipo de parámetro debe ser un objeto.
EDITAR:
Si bien esta respuesta no es incorrecta, sí recomiendo este enfoque. Usar una expresión lambda es mucho más fácil de leer y no requiere conversión de tipo. Ver aquí: https://stackoverflow.com/a/1195915/52551
fuente
Parameter
?fuente
Manera simple usando lambda así ...
O incluso podrías
delegate
usarThreadStart
así ...O usando VS 2019 .NET 4.5+ incluso más limpio así ...
fuente
Uso
ParametrizedThreadStart
.fuente
Utilice ParameterizedThreadStart .
fuente
Como ya se ha mencionado en varias respuestas aquí, la
Thread
clase actualmente (4.7.2) proporciona varios constructores y unStart
método con sobrecargas.Estos constructores relevantes para esta pregunta son:
y
que o bien toman un
ThreadStart
delegado o unParameterizedThreadStart
delegadoLos delegados correspondientes se ven así:
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íao solo
La firma del método correspondiente (llamado
Work
en este ejemplo) se ve así:Lo que queda es comenzar el hilo. Esto se hace usando cualquiera
o
Si bien
Start()
iniciaría el hilo y pasaríanull
como datos al método,Start(...)
se puede usar para pasar cualquier cosa alWork
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 delWork
método tiene que volver al tipo original, como en el siguiente ejemplo:El casting es algo que normalmente no quieres hacer.
¿Qué pasa si alguien pasa algo más que no es una cadena? Como esto parece no 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 un
InvalidCastException
que probablemente no notará porque simplemente termina el hilo.Como solución, esperaría obtener un genérico
ParameterizedThreadStart
delegado comoParameterizedThreadStart<T>
dóndeT
sería el tipo de datos que desea pasar alWork
método. Desafortunadamente, algo como esto no existe (¿todavía?).Sin embargo, hay un solución sugerida para este problema. Implica crear una clase que contenga tanto los datos que se pasarán al subproceso como el método que representa el método de trabajo de esta manera:
Con este enfoque, comenzaría el hilo de esta manera:
Por lo tanto, de esta forma, simplemente evitas dar vueltas y tienes una forma segura de proporcionar datos a un hilo ;-)
fuente
private static void MyMethod<T>(T myData) { T message = myData; Console.WriteLine($"the thread wrote: {message}"); }
message.Length
no es posible, etc.)if(myData.GetType() == typeof(string)) { var str = ((string)(object)myData).Length; }
. De todos modos, en lugar de usar su método de enhebrado, encontré un poco más cómodo de usarTasks<T>
, como por ejemplotasks.Add(Task.Run(() => Calculate(par1, par2, par3)))
, vea mi respuesta a continuación ( stackoverflow.com/a/59777250/7586301 )Estaba teniendo problemas en el parámetro pasado. Pasé un entero de un bucle for a la función y lo visualicé, pero siempre daba resultados diferentes. como (1,2,2,3) (1,2,3,3) (1,1,2,3), etc. con ParametrizedThreadStart delegado .
este simple código funcionó de maravilla
fuente
los
ParameterizedThreadStart
toma un parámetro. Puede usar eso para enviar un parámetro o una clase personalizada que contenga varias propiedades.Otro método es colocar el método que desea comenzar como miembro de la instancia en una clase junto con las propiedades de los parámetros que desea establecer. Cree una instancia de la clase, establezca las propiedades e inicie el hilo especificando la instancia y el método, y el método puede acceder a las propiedades.
fuente
Puede usar un delegado ParametrizedThreadStart :
fuente
Puede usar el método BackgroundWorker RunWorkerAsync y pasar su valor.
fuente
fuente
Propongo usar en
Task<T>
lugar deThread
; permite múltiples parámetros y se ejecuta realmente bien.Aquí hay un ejemplo de trabajo:
fuente
fuente