System.InvalidOperationException working with threads

1

The code is as follows, below the explanation ..

    Thread hilo = new Thread(NuevoHilo);
    hilo.Start(item);

    private void NuevoHilo(object item)
             {
              rtxMensajes = new Mensajes().NuevoMensaje(rtxMensajes, item.ToString(), tbxArchivo.Text, Color.Green);           
             }

    public RichTextBox NuevoMensaje(RichTextBox rtb, string unidad, string archivo, Color color)
             {
                string avance = "\r\n";
                rtb.SelectionStart = rtb.TextLength;  <---- EXCEPCION!!!
                rtb.SelectionLength = 0;

                rtb.SelectionColor = color;
                rtb.AppendText(String.Format("Se copio el archivo {0} en la unidad {1} {2}", archivo, unidad, avance));
                rtb.SelectionColor = rtb.ForeColor;
                return rtb;
             }

When the NuevoHilo method is executed and this instance is an object of the class Mensaje which in turn calls a method of this class and takes as parameter a RichTextBox object, an exception of type System.InvalidOperationException , which gives me the following description;

  

Invalid operation through sub-processes: The 'rtxMessages' control was accessed from a different sub-process than the one in which it was created.

To say that the object that I pass as a parameter is a RichTextBox that I have created in Form1, I try that every time I throw the thread I write the result in RichTextBox called rtxMensajes

    
asked by Edulon 01.10.2017 в 17:41
source

1 answer

3

When you go to access the controls created in the main thread you must do it in 2 ways: 1 Calling the Invoke method of your form or using BackgroundWorkers.

//Usando Invoke
Invoke(new MethodInvoker(() =>
{
  //Aqui va el código que modifica controles creados en el hilo principal
}));

//Usando BackgroundWorker
private void ThreadSafe(Action callback,Form form)
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.RunWorkerCompleted += (obj, e) =>
    {
        if (form.InvokeRequired)
            form.Invoke(callback);
        else
            callback();
    };
    worker.RunWorkerAsync();
}

//Lo llamas de esta manera
ThreadSafe(() =>{
   //Código que modifica controles creados en el hilo principal
}, this)  //this si estas en la clase del formulario principal

In short, your code would be in these two ways (use the one you want)

 public RichTextBox NuevoMensaje(RichTextBox rtb, string unidad, string archivo, Color color)
 {
    ThreadSafe(()=>{
        string avance = "\r\n";
        rtb.SelectionStart = rtb.TextLength;  <---- EXCEPCION!!!
        rtb.SelectionLength = 0;

        rtb.SelectionColor = color;
        rtb.AppendText(String.Format("Se copio el archivo {0} en la unidad {1} {2}", archivo, unidad, avance));
        rtb.SelectionColor = rtb.ForeColor;
    }, this);

    return rtb;
 }

or this:

public RichTextBox NuevoMensaje(RichTextBox rtb, string unidad, string archivo, Color color)
 {
    Invoke(new MethodInvoker(()=>{
       string avance = "\r\n";
        rtb.SelectionStart = rtb.TextLength;  <---- EXCEPCION!!!
        rtb.SelectionLength = 0;

        rtb.SelectionColor = color;
        rtb.AppendText(String.Format("Se copio el archivo {0} en la unidad {1} {2}", archivo, unidad, avance));
        rtb.SelectionColor = rtb.ForeColor;
    });
    return rtb;
 }

Try and tell me. Greetings

    
answered by 02.10.2017 / 15:39
source