tags:

views:

34

answers:

4

Hello guys I have a question regardless a old code a client needed a update.

This code add a thread.sleep(500) to keep the service alive, is reading from a com port some calls, and sending a alarm to other pcs now this time when I was sending some information to the machine in question this error pops out

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

    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) {
        Thread.Sleep(500);
        string data = port.ReadExisting();
        //try
        //{
            if (textBox1.TextLength == 30000)
            {
                textBox1.Text = "";
            }
        //}
        //catch (Exception) {}
        this.BeginInvoke(new setTextDeleg(si_DataRecived), new object[]{
        data});
    }

This is the funtion that writes on the com machine, does making a exception to eat the error is ok, or is there another better way to handle it?

PD: Sorry for my bad english, this is on C# 2008 vs

+1  A: 

You should modify GUI components like textboxes and labels only from the thread that created them which is the main thread. You may take a look at BackgroundWorker which simplifies this task in WinForms application. And here's another useful article illustrating the usage of the InvokeRequired property and the Invoke method.

Darin Dimitrov
A: 

It's not a good idea to simply swallow this exception. The exception is occurring because you are not allowed to modify UI components from any thread other than the UI thread (the thread that created them). Instead, check out this MSDN article on how to pass information between worker threads (your thread that sleeps) and UI threads to update the text box in the correct manner.

Chris Thompson
Thanks a lot seems like this is what I need.
Enrique
A: 

The problem is because Windows Forms Controls are not thread-safe, and it would seem that the control is not being invoked properly for a thread-safe call. You can use the BackgroundWorker class or you can invoke it yourself. Here is a small code example.

    // Delegate used by our worker thread to invoke our control
    private delegate void ProgressDelegate(int value);

    // Callback method used for our delegate
    private void ProgressCallback(int value) {
        progressBar1.Value = value;
    }

    protected override void OnShown(EventArgs e) {
        Thread thread = new Thread(new ThreadStart(MyThreadWorker));
        thread.IsBackground = true;
        thread.Start();
    }

    // Thread method
    private void MyThreadWorker() {
        // Setup the delegate
        ProgressDelegate mydelegate = new ProgressDelegate(ProgressCallback);

        // Do some work
        int pos = 0;
        do {
            pos++;

            // Make a thread-safe call to our control and invoke our callback on the original thread
            // Original thread: The thread the form and control were created on
            progressBar1.Invoke(mydelegate, pos);
        } while (pos < 100);
    }
David Anderson
A: 

I'm guessing what some of your other code looks like, but you could probably move this

 if (textBox1.TextLength == 30000)
        {
            textBox1.Text = "";
        }

to the si_DataRecived method, so that it gets executed as part of the BeginInvoke call, the target of which will execute on the main (UI) thread.

Jay