una traves todos thread subprocesos subproceso seguras requiere realizar que para otro los llamó llamar llamadas interfaz función formularios form evaluación ejemplo ejecuten diferente desde controles control como checkforillegalcrossthreadcalls aplicación aplanó acceder c# thread-safety

c# - traves - realizar llamadas seguras para subprocesos en controles de formularios windows forms



La forma más corta de escribir un método de acceso seguro para subprocesos a un control de formularios de Windows (5)

1) Usando delegado anónimo

private void SetText(string text) { if (this.InvokeRequired) { Invoke(new MethodInvoker(delegate() { SetText(text); })); } else { this.textBox1.Text = text; } }

2) enfoque AOP

[RunInUIThread] private void SetText(string text) { this.textBox1.Text = text; }

http://weblogs.asp.net/rosherove/archive/2007/05.aspx?PageIndex=2

3) Usando expresiones lambda (delineadas por otros).

En este articulo:

El autor utiliza el siguiente método para realizar llamadas seguras para subprocesos a un control de Windows Forms:

private void SetText(string text) { // InvokeRequired required compares the thread ID of the // calling thread to the thread ID of the creating thread. // If these threads are different, it returns true. if (this.textBox1.InvokeRequired) { SetTextCallback d = new SetTextCallback(SetText); this.Invoke(d, new object[] { text }); } else { this.textBox1.Text = text; } }

¿Hay una manera más corta de lograr lo mismo?


Edit: debo mencionar que no consideraría esto como una mejor práctica

Si está utilizando 3.5 puede hacer un método de extensión al efecto de:

public static void SafeInvoke(this Control control, Action handler) { if (control.InvokeRequired) { control.Invoke(handler); } else { handler(); } }

esto es básicamente tomado de: Here

Entonces úsalo como:

textBox1.SafeInvoke(() => .... );

Por supuesto, modifique la extensión, etc. para sus usos.


Esto puede ser obvio para la mayoría, pero puede aceptar la respuesta aceptada y agregar otro método si necesita recuperar el valor ...

public static T SynchronizedFunc<T>(this ISynchronizeInvoke sync, Func<T> func) { if (!sync.InvokeRequired) { // Execute the function return func(); } // Marshal onto the context return (T) sync.Invoke(func, new object[] { }); }

Utilicé esto recientemente para controlar el formulario de forma segura para subprocesos ...

var handle = f.SynchronizedFunc(() => f.Handle);


La solución más corta que he encontrado se muestra en el ejemplo de botón a continuación, donde el objetivo es cambiar el texto de un botón.

if (buttonX.InvokeRequired) buttonX.Invoke((Action)(() => buttonX.Text = "Record")); else buttonX.Text = "Record";


C # 3.0 y después:

Un método de extensión generalmente sería el camino a seguir, ya que siempre querrá realizar una acción en una implementación de interfaz ISynchronizeInvoke , es una buena opción de diseño.

También puede aprovechar los métodos anónimos (cierres) para tener en cuenta el hecho de que no sabe qué parámetros pasar al método de extensión; El cierre capturará el estado de todo lo necesario.

// Extension method. static void SynchronizedInvoke(this ISynchronizeInvoke sync, Action action) { // If the invoke is not required, then invoke here and get out. if (!sync.InvokeRequired) { // Execute action. action(); // Get out. return; } // Marshal to the required context. sync.Invoke(action, new object[] { }); }

Entonces lo llamarías así:

private void SetText(string text) { textBox1.SynchronizedInvoke(() => textBox1.Text = text); }

Aquí, el cierre es sobre el parámetro de text , ese estado se captura y se pasa como parte del delegado de Action pasa al método de extensión.

Antes de C # 3.0:

No tiene el lujo de las expresiones lambda, pero aún puede generalizar el código. Es casi lo mismo, pero no es un método de extensión:

static void SynchronizedInvoke(ISynchronizeInvoke sync, Action action) { // If the invoke is not required, then invoke here and get out. if (!sync.InvokeRequired) { // Execute action. action(); // Get out. return; } // Marshal to the required context. sync.Invoke(action, new object[] { }); }

Y luego lo llamas con sintaxis de método anónimo:

private void SetText(string text) { SynchronizedInvoke(textBox1, delegate() { textBox1.Text = text; }); }