2010-07-05 19 views
8

Estoy usando web workers para hacer un poco de trabajo intensivo de CPU pero tengo el requisito de que el trabajador responda a los mensajes del script principal mientras el trabajador está todavía procesando.Cómo evitar que HTML5 Web Workers se bloquee respondiendo correctamente a los mensajes del padre

Sin embargo, el trabajador no responderá mensajes mientras está bloqueado en un bucle de procesamiento, y no he encontrado una manera de decir sondear la cola de mensajes. Por lo tanto, parece que la única solución es interrumpir el procesamiento en un intervalo para permitir el mantenimiento de cualquier mensaje en la cola.

Las opciones obvias son utilizar un temporizador (digamos con setInterval), sin embargo, he leído que el retraso mínimo entre disparos es bastante largo (http://ajaxian.com/archives/settimeout-delay), lo cual es desafortunado ya que ralentizará mucho el procesamiento.

¿Cuáles son los pensamientos de otras personas sobre esto? Voy a intentar que el trabajador envíe onmessage a sí mismo al final de cada onmessage, implementando efectivamente un paso del bucle de procesamiento por evento recibido de sí mismo, pero solo quería ver si alguien tenía alguna idea al respecto.

Gracias,

+0

El enganchar https://stackoverflow.com/a/32269593/632951 – Pacerier

Respuesta

6

Un trabajador puede generar sub trabajadores. Puede hacer que su trabajador principal actúe como su cola de mensajes, y cuando recibe una solicitud para una operación de larga ejecución, engendre un trabajador secundario para procesar esos datos. El trabajador secundario puede enviar los resultados nuevamente al trabajador principal para eliminar el evento de la cola y devolver los resultados al hilo principal. De esta forma, su trabajador principal siempre tendrá la libertad de escuchar nuevos mensajes y usted tendrá el control total de la cola.

--Nick

+1

creo que esto no funcionará si el cálculo se debe detener y reanudar. No he encontrado una solución para esto todavía. Ejemplo: http: //gist.github.com/607058 – Giacomo

+0

@nciagra, esta respuesta no funciona: usted simplemente había empujado el problema un paso hacia arriba. Entonces, ¿qué pasa si engendras sub trabajadores? Ahora, esos subtrabajadores están ocupados haciendo el cálculo y no puedes interrumpirlos desde tu principal trabajador. Supongo que [la solución de intervalo anterior] (https://stackoverflow.com/a/10180450/632951) (ahora dentro del propio webworker) es la única manera si tenemos que interrumpir al trabajador, los webworkers realmente necesitan un mecanismo de interrupción real como qué Java puede hacer. – Pacerier

0

teniendo el mismo problema que busqué los trabajadores web borrador y encontré algo en la sección Processing model, los pasos del 9 al 12. Por lo que tengo entendido, un trabajador que se inicia el procesamiento de una tarea se no procesar otro hasta que se complete el primero. Entonces, si no le importa detener y reanudar una tarea, la respuesta de nciagra debería dar mejores resultados que reprogramar cada iteración de la tarea.

Aún así, investigar.

+0

La respuesta de nciagra no funciona. – Pacerier

3

Me encontré con este problema yo mismo cuando jugaba con los trabajadores por primera vez. También debatí sobre el uso de setInterval, pero sentí que este sería un enfoque un tanto raro para el problema (y ya había ido por este camino para mi multithreading emulado). En cambio, decidí terminar a los trabajadores del hilo principal (worker.terminate()) y volver a crearlos si la tarea en la que están involucrados necesita ser interrumpida. La recolección de basura, etc. parecía ser manejada en mi prueba.

Si hay datos de estas tareas que desea guardar, siempre puede volver a publicarlos en la secuencia principal para su almacenamiento a intervalos regulares, y si hay alguna lógica que desee implementar con respecto a si se terminan o no. , puede publicar los datos relevantes a intervalos regulares suficientes para permitirlo.

Engendrar subtrabajadores conduciría a la misma serie de problemas de todos modos; aún tendrías que terminar los subtrabajadores (o crear nuevos) de acuerdo con alguna lógica, y no estoy seguro de que sea tan bien soportado (en cromo, por ejemplo).

James

+1

teniendo el mismo problema, y ​​usó la misma solución. Para no perder los cálculos realizados por el webworker estoy publicando datos calculados en algunos intervalos en la "ventana" principal, y luego cuando reaparezco el webworker empiezo con el resultado calculado hasta ahora – Picard

+0

Desafortunadamente, worker.terminate() pierde memoria. .. podría funcionar si se usa esporádicamente, pero en mi caso específico cuelga el navegador rápidamente https://bugs.chromium.org/p/chromium/issues/detail?id=502298 – solendil

Cuestiones relacionadas