¿Cómo devuelvo un valor de un hilo?
c#
.net
multithreading
Sam
fuente
fuente
lock(value) { value = "Hello world"; }
sería mejor manejar la escritura de valores de múltiples hilos?value
están realizando lecturas ni escrituras al mismo tiempo. Pero, sí, siempre tenga en cuenta cuándo es necesario un candado.Depende de cómo desee crear el hilo y la versión de .NET disponible:
.NET 2.0+:
A) Puede crear el
Thread
objeto directamente. En este caso, podría usar "cierre" - declarar variable y capturarla usando expresión lambda:B) Puede usar delegados y un
IAsyncResult
valor de retorno delEndInvoke()
método:C) Puedes usar la
BackgroundWorker
clase. En este caso, puede usar la variable capturada (como con elThread
objeto) o manejar elRunWorkerCompleted
evento:.NET 4.0+:
A partir de .NET 4.0, puede usar Task Parallel Library y
Task
class para iniciar sus hilos. La clase genérica leTask<TResult>
permite obtener el valor de retorno de laResult
propiedad:.NET 4.5+:
A partir de .NET 4.5, también puede usar
async
/await
keywords para devolver el valor de la tarea directamente en lugar de obtener laResult
propiedad:Nota: el método que contiene el código anterior debe estar marcado con la
async
palabra clave.Por muchas razones, el uso de Task Parallel Library es una forma preferible de trabajar con subprocesos.
fuente
Usaría el enfoque BackgroundWorker y devolvería el resultado en e.Result.
EDITAR:
Esto se asocia comúnmente con WinForms y WPF, pero puede ser utilizado por cualquier tipo de aplicación .NET. A continuación, se muestra un código de muestra para una aplicación de consola que usa BackgroundWorker:
Salida:
ACTUALIZACIÓN 2014
Vea la respuesta de @ Roger a continuación.
https://stackoverflow.com/a/24916747/141172
Señala que puede usar una Tarea que devuelva un
Task<T>
, y compruebeTask<T>.Result
.fuente
Un hilo no es un método, normalmente no "devuelve" un valor.
Sin embargo, si está tratando de recuperar un valor de los resultados de algún procesamiento, tiene muchas opciones, las dos principales son:
Realmente depende de cómo esté creando el hilo y cómo quiera usarlo, así como del lenguaje / marco / herramientas que esté usando.
fuente
Mi clase favorita, ejecuta cualquier método en otro hilo con solo 2 líneas de código.
uso
Tenga en cuenta que longFunctionComplete NO se ejecutará en el mismo hilo que starthework.
Para los métodos que toman parámetros, siempre puede usar cierres o expandir la clase.
fuente
Aquí hay un ejemplo simple usando un delegado ...
Hay una serie excelente sobre subprocesos en Threading en C # .
fuente
Simplemente use el enfoque de delegado.
Ahora haga la función Multiplicar que funcionará en otro hilo:
fuente
Me encontré con este hilo cuando también intentaba obtener el valor de retorno de un método que se ejecuta dentro de un hilo. Pensé en publicar mi solución que funciona.
Esta solución utiliza una clase para almacenar tanto el método a ejecutar (indirectamente) como el valor devuelto. La clase se puede utilizar para cualquier función y cualquier tipo de retorno. Simplemente crea una instancia del objeto usando el tipo de valor de retorno y luego pasa la función para llamar a través de un lambda (o delegado).
Implementación de C # 3.0
Para usar este código, puede usar un Lambda (o un delegado). Aquí está el ejemplo usando lambdas:
Implementación de VB.NET 2008
Cualquiera que use VB.NET 2008 no puede usar lambdas con métodos de devolución sin valor. Esto afecta a la
ThreadedMethod
clase, así que haremos queExecuteMethod
devuelva el valor de la función. Esto no duele nada.fuente
Con el último .NET Framework, es posible devolver un valor de un subproceso separado usando una Tarea, donde la propiedad Result bloquea el subproceso que llama hasta que finaliza la tarea:
Para obtener más información, consulte http://msdn.microsoft.com/en-us/library/dd537613(v=vs.110).aspx
fuente
Los delegados de ThreadStart en C # que se usan para iniciar los subprocesos tienen el tipo de retorno 'void'.
Si desea obtener un 'valor de retorno' de un hilo, debe escribir en una ubicación compartida (de una manera adecuada y segura para el hilo) y leer desde allí cuando el hilo haya terminado de ejecutarse.
fuente
Si no desea usar un BackgroundWorker y solo usa un Thread normal, puede activar un evento para devolver datos como este:
fuente
thread1_
parte de su cableado del AsyncCompletedEventHandler . Si mi edición fue un error, por favor ayúdenme a comprender lo que estaba sucediendo allí.thread1_Thread1Completed +=
porquethread1_Thread1Completed
es el nombre de una función, por lo que no puede ponerlo en el lado izquierdo de un operador de asignación. El lado izquierdoThread1Completed +=
se usa porque es un evento, por lo que puede aparecer en el lado izquierdo del operador de asignación para agregar controladores de eventos. Verpublic event AsyncCompletedEventHandler Thread1Completed;
#region
sección antes. Miré. ¡Honesto! :)Los hilos realmente no tienen valores de retorno. Sin embargo, si crea un delegado, puede invocarlo de forma asincrónica a través del
BeginInvoke
método. Esto ejecutará el método en un subproceso de grupo de subprocesos. Puede obtener cualquier valor de retorno, como llamar a través deEndInvoke
.Ejemplo:
GetAnswer
se ejecutará en un subproceso de grupo de subprocesos y cuando se complete, puede recuperar la respuesta a través deEndInvoke
como se muestra.fuente
El BackgroundWorker es agradable cuando se desarrollan para Windows Forms.
Supongamos que desea aprobar una clase simple de un lado a otro:
Escribí una clase corta que hace lo siguiente:
Desde dentro de la rutina del hilo:
Agregar un delegado puede ser útil para publicar sus datos directamente en su hilo principal, pero es posible que deba usar Invoke si algunos de los elementos de datos no son seguros para el hilo.
Para probar esto, cree una pequeña aplicación de consola y colóquela en el archivo Program.cs :
Aquí hay una captura de pantalla de lo que obtuve con esto:
Espero que otros puedan entender lo que he intentado explicar.
Disfruto trabajando en hilos y usando delegados. Hacen que C # sea muy divertido.
Apéndice: para codificadores VB
Quería ver qué implicaba escribir el código anterior como una aplicación de consola VB. La conversión involucró algunas cosas que no esperaba, así que actualizaré este hilo aquí para aquellos que quieran saber cómo hilo en VB.
fuente
fuente
test(){ Thread.Sleep(5000); /*Highly time demanding process*/ return "Returned from test()";}
. En este caso, el hilo independiente no tendría tiempo para asignar un nuevo valor a lareturnValue
variable. Como último recurso, puede guardar una referencia de hilovar standaloneThread = new Thread(()=> //...);
y después de eso, iniciarlo de forma sincronizadastandaloneThread.Start(); standaloneThread.Join();
. Pero esta ciertamente no es la mejor práctica.Una solución simple es pasar un parámetro por referencia a la función que se está ejecutando en el hilo y cambiar su valor en el hilo.
Si no puede cambiar la función que se está ejecutando en la banda de rodadura, puede envolverla en otra función:
fuente
Puede usar este código:
fuente
No soy un experto en subprocesos, por eso lo hice así:
Creé un archivo de configuración y
Dentro del nuevo hilo:
Luego recojo ese valor cada vez que lo necesito.
fuente