2012-03-18 8 views
5

utilizo un BackgroundWorker y hacer esto:¿Por qué no conseguir la "operación de la Cruz-hilo no válida" error

private void loadNewAsyncToolStripMenuItem_Click(object sender, EventArgs e) 
{ 
    this.Text = "RunWorkerAsync()"; 
    backgroundWorkerLoading.RunWorkerAsync(); 
} 
private void backgroundWorkerLoading_DoWork(object sender, DoWorkEventArgs e) 
{ 
    UnsafeThreadMethod("hello"); 
    EvenUnsaferThreadMethod(); 
} 

Y ahora los dos métodos.

private void UnsafeThreadMethod(string text) 
{ 
    toolStripLabelRssFeedData.Text = text; 
} 

private void EvenUnsaferThreadMethod() 
{ 
    panelLoading.Visible = true; 
} 

No entiendo por qué UnsafeThreadMethod no arroja la siguiente excepción pero EvenUnsaferThreadMethod hace.

Operación de cruce de hilos no válida: controle 'panelLoading' al que se accede desde un hilo que no sea el> thread en el que se creó.

De acuerdo con el mensaje es porque toolStripLabelRssFeedData se creó en el mismo hilo pero no lo era.

Pensé que no puedo llamar a los controles creados por el hilo principal y tengo que usar el evento ProgressChanged. ¿Que esta pasando?

Y tengo una segunda pregunta. ¿Cuál es la ventaja de hacerlo así cuando puedo usar ProgressChanged? ¿Que debería hacer?

private void EvenUnsaferThreadMethod() 
{ 
    if (panelLoading.InvokeRequired) 
    { 
     panelLoading.Invoke(new MethodInvoker(() => { EvenUnsaferThreadMethod(); })); 
    } 
    else 
    { 
     panelLoading.Visible = true; 
    } 
} 

Respuesta

5

A la primera pregunta:

  • la excepción entre subprocesos es deliberadamente lanzado en modo de depuración. Esto significa que hay una verificación de código (condicional) en InvokeRequired integrado en la mayoría de los controles de GUI. Como el Panel

  • Al parecer, ToolstripLabel no hace esta comprobación. Dado que no se deriva de Control que podría ser porque está fuera del alcance de esta red de seguridad.

Desde el descargo de responsabilidad estándar "los miembros de instancias se garantiza que sea seguro para subprocesos" se aplica a la ToolstripLabel me acaba de ir con la lógica normal InvokeRequired cuando se ajusta el texto.

+1

Creo que esta respuesta aborda lo que el OP estaba preguntando, y por eso una llamada que parecía claramente insegura no arrojaba una excepción. Todo gira en torno al hecho de que ToolStripLabel no se deriva de Control y, por lo tanto, no se está comprobando la seguridad de las hebras. Simplemente funciona, pero como otros han señalado, no puedes contar con eso para ser verdad para siempre. –

0

La ventaja de la segunda opción es que funciona :)

Todos los elementos de interfaz de usuario se crean en el hilo principal de la interfaz de usuario y, lo que es más importante, desde esta perspectiva cuestión, es que puede ser solo dentro de ese hilo.

Esta es la razón por la que su primera caso de que falle y que es la razón de su segundo caso funcionará. Invoke()... redirigirá la llamada de merhod requerida al hilo principal de la interfaz de usuario.

Espero que esto ayude.

+0

Gracias por su respuesta. Dijiste 'UnsafeThreadMethod' no debería funcionar porque las cosas de la interfaz de usuario están en un hilo diferente, pero de alguna manera lo hace y eso es lo que no entiendo. Además, la última pregunta fue si es mejor utilizar el material de Invoke o 'ProgressChanged' y 'RunWorkerCompleted' (que funcionaría porque están de nuevo en el hilo derecho). – pelz

+0

Que el primer caso * a veces * funciona me suena extraño. ¿Qué pasa con el segundo caso? Considerando que en su método tiene acceso al elemento UI, * tiene que * usar 'Invoke' para redirigir la llamada al hilo UI. No puede funcionar de otra manera. – Tigran

+0

De alguna manera, porque el comportamiento no es determinante. Se puede romper a voluntad, en Service Pack, en la revisión. – TomTom

3

Para su primera pregunta, no estoy del todo seguro, pero una revisión en línea parece mostrar que a veces esto no generará una excepción, pero no actualizará la etiqueta. ¿Es ese el caso aquí? ¿Su etiqueta se está actualizando junto con no tener ninguna excepción?

Sin embargo, puedo responder a su segunda pregunta en este momento. El evento ProgressChanged está destinado exactamente a lo que parece. Se supone que se debe invocar para que el subproceso de la interfaz de usuario conozca el estado del backgroundworker para que pueda actualizarse correctamente. El hilo de llamada original (IU en este caso) es el que se utiliza para el ProgressChanged, por lo que cuando se actualice no necesita llamar al Invoke. Pero, en realidad, esto solo debería hacerse para mostrar el progreso de un trabajador de segundo plano.

Ahora, si no es una actualización que está intentando pasar al método de llamada, entonces le sugiero que simplemente devuelva los datos de devolución a través del evento RunWorkerCompleted. Esto pasa todos tus datos finales al hilo original (UI), para que pueda actualizar la interfaz de usuario sin necesidad de un Invoke.

Así que, sí, su llamada al Invoke funcionará. Sin embargo, comprender para qué sirve cada uno de los otros eventos puede ayudarlo a comprender por qué usarlo de una manera u otra.Tal vez un evento ProgressChanged se adapta mejor? También puede evitar que su código tenga invocaciones innecesarias.

actualización a la primera q

todavía no puedo encontrar nada sobre el toolstrip no necesitar la invocación. De hecho, estoy encontrando lo opuesto usando búsquedas de Google como "tooltriplabel no cross thread exception" o "toolstriplabel invoke", etc. Sin embargo, como henk mencionó, la etiqueta de herramientas no hereda del control, por lo que podría explicar por qué no se requiere invocación. Sin embargo, mi sugerencia es suponer que actuará como cualquier otro control de UI y asegúrese de que esté actualizado en el hilo de UI para estar seguro. no confíe en las peculiaridades. Mejor prevenir que curar, nunca se sabe si este tipo de cosas podrían cambiar, sobre todo porque es lógicamente un elemento de interfaz de usuario para la mayoría ..,

+0

Gracias por su respuesta. En cuanto a la primera pregunta: sí, actualizará la etiqueta muy bien. Tu respuesta a mi segunda pregunta aclaro mucho las cosas. Creo que en mi caso 'RunWorkerCompleted' es el camino a seguir. – pelz

+0

Me alegra ayudar. Actualicé mi respuesta para dar mi opinión sobre la etiqueta después de más investigaciones –

Cuestiones relacionadas