2010-04-08 16 views
6

Estoy intentando actualizar un cuadro de texto. Pensé que mi código de enhebrado solucionaría el problema, pero no es así. ¿Alguien puede ayudarme con esto?Errores de subprocesos múltiples en C#

new Thread((ThreadStart)delegate { txtCapacitance.Text = Math.Round(capacitance, 3).ToString(); }).Start(); 

da el siguiente error:

Cross-thread operation not valid: Control 'txtCapacitance' accessed from a thread other than the thread it was created on.

Tenga en cuenta que todo esto se va a iniciar por una función DataReceived que se llama cada vez que se reciben datos USB.

Respuesta

4

Usted no debe tener una mirada en el uso de BackgroundWorker Class

un vistazo a

C# BackgroundWorker Tutorial.

+0

Esto no solucionará el problema. Los trabajadores de segundo plano todavía ejecutan un hilo diferente al hilo de la interfaz de usuario. –

+0

@Marcelo Cantos, ¿Has leído la documentación? * Debe tener cuidado de no manipular ningún objeto de interfaz de usuario en su controlador de eventos DoWork. En su lugar, comuníquese con la interfaz de usuario a través de los eventos ProgressChanged y RunWorkerCompleted. * –

+0

tiene razón; Me equivoco; mis disculpas. Confundí esto con un grupo de hilos normal. –

6

Los objetos de interfaz de usuario solo se pueden invocar desde el subproceso de interfaz de usuario. Esto se puede lograr a través del método Invoke del Control:

txtCapacitance.Invoke((Action)(() => { txtCapacitance.Text = Math.Round(capacitance, 3).ToString(); })); 
+0

Aparece este error: No se puede convertir la expresión lambda para escribir 'System.Delegate' porque no es un tipo de delegado – Adam

+0

Lo siento, tienes que hacer un molde. Lo he arreglado –

1

actualizaciones a cualquier elemento de la interfaz de usuario se deben hacer en la UI-hilo. Sin duda, puede calcular su valor en otro hilo, pero debe usar el método .Invoke(...) del control para realizar la actualización.

0

prueba este

//delegate 
delegate void updateTextboxDelegate(string value); 

private void updateDisplay(string value) 
{ 
    txtCapacitance.Text = value; 
} 

//the thread 
string msg = string.empty; 
var th =new Thread(()=>{BeginInvoke(new updateTextboxDelegate(updateDisplay), msg); }); 
th.Start(); 

la esperanza de que va a trabajar para usted.

0

Debe asegurarse de actualizar textBox desde el mismo hilo que lo ha creado.

Para este propósito mismo crea ayudante de clase como esta y utilizar las extensiones de este lugar de utilizar de manera normal (en este caso son dos extensiones que hice para mí mismo, pero lo interesante que es changeText):

public static class ControlExtensions { 
    public static void changeStatus(this Control varControl, bool varState) { 
     if (varControl.InvokeRequired) { 
      varControl.BeginInvoke(new MethodInvoker(() => changeStatus(varControl, varState))); 
     } else { 
      varControl.Enabled = varState; 
     } 
    } 
    public static void changeText(this Control varControl, string varText) { 
     if (varControl.InvokeRequired) { 
      varControl.BeginInvoke(new MethodInvoker(() => changeText(varControl, varText))); 
     } else { 
      varControl.Text = varText; 
     } 
    } 
    public static DateTime readDateValue(this DateTimePicker varControl) { 
     if (varControl.InvokeRequired) { 
      return (DateTime) varControl.Invoke(new Func<DateTime>(() => readDateValue(varControl))); 
     } else { 
      return varControl.Value; 
     } 
    } 
    public static bool ReadStatus(this CheckBox varControl) { 
     if (varControl.InvokeRequired) { 
      return (bool) varControl.Invoke(new Func<bool>(() => ReadStatus(varControl))); 
     } 
     return varControl.Checked; 
    } 
    public static bool ReadStatus(this RadioButton varControl) { 
     if (varControl.InvokeRequired) { 
      return (bool) varControl.Invoke(new Func<bool>(() => ReadStatus(varControl))); 
     } 
     return varControl.Checked; 
    } 
    public static string readText(this Control varControl) { 
     if (varControl.InvokeRequired) { 
      return (string) varControl.Invoke(new Func<string>(() => readText(varControl))); 
     } else { 
      return varControl.Text; 
     } 
    } 
    public static bool readEnabled(this Control varControl) { 
     if (varControl.InvokeRequired) { 
      return (bool) varControl.Invoke(new Func<bool>(() => readEnabled(varControl))); 
     } else { 
      return varControl.Enabled; 
     } 
    } 

} 

Entonces lo usa así: txtCapacitance.changeText("new text");

Cuestiones relacionadas