Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Cross-thread operation error

Status
Not open for further replies.

abcfantasy

Programmer
Jun 3, 2006
110
DK
I don't know why I'm still getting this error, even after using delegates and the invoke method.

This is what I have:

A form is first displayed, where you enter some settings like IP and so on. When you click the button 'Join' I have the following code:

Code:
private void btnJoin_Click( object sender, EventArgs e )
        {
            formGame game = new formGame( txtName.Text, txtIP.Text );
            this.Hide();
            game.ShowDialog();
            game.Dispose();
            this.Show();           
        }

It will create another form passing the settings (name and IP) as parameters. When the other form is created, it will connect to the server and wait for data.

When data is receieved, it passes the string data to the following method which will output on a textbox.

Code:
private void CommunicationReceived( string text )
        {
                if ( txtLog.InvokeRequired )
                {
                    CommReceivedDelegate d = new CommReceivedDelegate( CommunicationReceived );
                    this.Invoke( d, text );
                }
                else
                {
                    txtLog.Text = text;
                }
         }

When I run the program and click join, the debugger halts on the line "game.ShowDialog()" with the following error: Cross-thread operation not valid. Control 'txtLog' accessed from a thread other than the thread it was created on.

I tried to use game.Show() instead of ShowDialog(), and somehow, the first client that connects would work perfectly, but the same error occurs for the second client.

Any reasons why this is happening? And any possible work arounds?

(Note: The code was changed and simplified from the original, so tell me if more detail is required)

Thanks in advance
Andrew

ABC -
 
if CommunicationReceived is excuted on a new thread you cannot access object in the parent thread. to interact with the parent thread (gui) you need to return the values to the parent thread. the parent thread can then set the values on the gui.

BackgroundWorker object makes this pretty easy.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Thank you for your reply.

But I'm not sure about this. I don't think BackgroundWorker can help.

The thing is this. I've got a class called 'Client' which handles the connection and so on. It contains the following parts:

Code:
class Client
{
        [b]public delegate void CommunicationReceivedHandler( string text );
        public event CommunicationReceivedHandler CommunicationReceived;[/b]

        private void OnDataReceived( IAsyncResult async )
        {
            //get received data
            ..

            [b]CommunicationReceived( stringData );[/b]

            //wait for data again
            WaitForData( socketPkt );
        }
}

In formGame.cs I obviously set the delegates and events.

Code:
public class formGame : Form
{
        [b]private Client.CommunicationReceivedHandler CommunicationReceivedDelegate;[/b]

        public formGame( .. )
        {
            ..
            [b]CommunicationReceivedDelegate = new Client.CommunicationReceivedHandler( CommunicationReceived );
            client.CommunicationReceived += CommunicationReceivedDelegate;[/b]
            ..   
        }

        private void CommunicationReceived( string text )
        {
            //seen in my first post
        }
}

Does this make things clearer?
How would I have to return the values to the parent thread? Or how can the BackgroundWorker be used?

Thanks again
Andrew

ABC -
 
does this work for you? if so you don't need the BW object.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
I did google about it, and what I get is that I need to declare a delegate and use the InvokeRequired property and Invoke method. It had solved an earlier problem I had, but this problem still persists.

I traced the program, and the first time that data is receieved, InvokeRequired is false, so (from the code posted in the first post) it skips the if condition and goes to the else where it changes the text, which results in the cross thread error.

ABC -
 
how is this code different than your other working code?

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Alright, I think I solved it. Not sure if it's a clean way.

What I did is stopped checking if InvokeRequired is true, and always Invoke the method.

Could it have been possible that InvokeRequired was false when in fact an Invoke was actually required? I don't know, I'm a bit confused on why the error was occuring.

But thank you again for your help.
Andrew

ABC -
 
I'm not sure I understood you well.

I'm creating a new instance of formGame from the first form, when the 'Join' button is clicked. (as you can see in the first chunk of code I wrote in the first post)

ABC -
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top