By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,183 Members | 1,190 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,183 IT Pros & Developers. It's quick & easy.

Cross Thread Communications

P: n/a
Hi everyone,

I have a Socket derived class that parses the received data into a message,
populates a object with that information and then tries to send an event to
inform the owner of the socket that there is message to be processed. But
this is not working as the socket receiver method seems to be in a different
thread then the form that owns the socket.

The receive callback gets the data from the socket and process the
information, once it constructs a full message from it then it calls a
delegate if the delegate is set.

The method that handles this event needs to change some controls on the form
and when I do that I get the exception:
Cross-thread operation not valid: Control 'syncButton' accessed from a
thread other than the thread it was created on.

I would appreciate any suggestions on solving this.

class LSSocket : Socket
{
public event ProcessMessageHandler ProcessMessageEvent;

public void OnReceiveData(IAsyncResult)
{
....
if (ProcessMessageEvent != null)
{
ProcessMessageEvent(this, new ProcessMessageArgs(Msg));
}
}
}

class ProcessMessageArgs : System.EventArgs
{
public ProcessMessageArgs(LSMessage msg)
{
this.msg = msg;
}
public LSMessage msg;
}
delegate void ProcessMessageHandler(object sender, ProcessMessageArgs
e);

I would have had to use PostThreadMessage in native windows development, but
I can't figure out what I need to use in this situation.

AliR.
Aug 5 '08 #1
Share this Question
Share on Google+
6 Replies


P: n/a
On Aug 5, 12:48 pm, "AliR \(VC++ MVP\)" <A...@online.nospamwrote:
Hi everyone,

I have a Socket derived class that parses the received data into a message,
populates a object with that information and then tries to send an event to
inform the owner of the socket that there is message to be processed. But
this is not working as the socket receiver method seems to be in a different
thread then the form that owns the socket.

The receive callback gets the data from the socket and process the
information, once it constructs a full message from it then it calls a
delegate if the delegate is set.

The method that handles this event needs to change some controls on the form
and when I do that I get the exception:
Cross-thread operation not valid: Control 'syncButton' accessed from a
thread other than the thread it was created on.

I would appreciate any suggestions on solving this.

class LSSocket : Socket
{
public event ProcessMessageHandler ProcessMessageEvent;

public void OnReceiveData(IAsyncResult)
{
....
if (ProcessMessageEvent != null)
{
ProcessMessageEvent(this, new ProcessMessageArgs(Msg));
}
}
}

class ProcessMessageArgs : System.EventArgs
{
public ProcessMessageArgs(LSMessage msg)
{
this.msg = msg;
}
public LSMessage msg;
}
delegate void ProcessMessageHandler(object sender, ProcessMessageArgs
e);

I would have had to use PostThreadMessage in native windows development, but
I can't figure out what I need to use in this situation.

AliR.
Use Control.Invoke to execute the event in the UI thread.
Aug 5 '08 #2

P: n/a
"Ignacio Machin ( .NET/ C# MVP )" <ig************@gmail.comwrote in
message
news:1f**********************************@m44g2000 hsc.googlegroups.com...
On Aug 5, 12:48 pm, "AliR \(VC++ MVP\)" <A...@online.nospamwrote:
>Hi everyone,

I have a Socket derived class that parses the received data into a
message,
populates a object with that information and then tries to send an event
to
inform the owner of the socket that there is message to be processed.
But
this is not working as the socket receiver method seems to be in a
different
thread then the form that owns the socket.

The receive callback gets the data from the socket and process the
information, once it constructs a full message from it then it calls a
delegate if the delegate is set.

The method that handles this event needs to change some controls on the
form
and when I do that I get the exception:
Cross-thread operation not valid: Control 'syncButton' accessed from a
thread other than the thread it was created on.

I would appreciate any suggestions on solving this.

class LSSocket : Socket
{
public event ProcessMessageHandler ProcessMessageEvent;

public void OnReceiveData(IAsyncResult)
{
....
if (ProcessMessageEvent != null)
{
ProcessMessageEvent(this, new
ProcessMessageArgs(Msg));
}
}
}

class ProcessMessageArgs : System.EventArgs
{
public ProcessMessageArgs(LSMessage msg)
{
this.msg = msg;
}
public LSMessage msg;
}
delegate void ProcessMessageHandler(object sender, ProcessMessageArgs
e);

I would have had to use PostThreadMessage in native windows development,
but
I can't figure out what I need to use in this situation.

AliR.

Use Control.Invoke to execute the event in the UI thread.
I looked at Control.Invoke, but wasn't really sure where it would apply. A
little more explanation would be great.

Are you saying that I have to use that in event hander method in my form
class to do the UI manipulation? Or am I supposed to use it in place of the
event hander call? Or am I supposed to call the event handler delegate
using the Invoke method?

Here is the event handler method:
public void ProcessMessage(object sender, ProcessMessageArgs e)
{
switch (e.msg.m_Command)
{
case MSG_SERVERIP: ServerIP = e.msg.m_Address;
ServerPort = 29308;
syncButton.Enabled = true;
break;
default: Debug.Print("Oh Oh");
break;
}
}

AliR
Aug 5 '08 #3

P: n/a
"AliR (VC++ MVP)" <Al**@online.nospamwrote in message
news:QW*******************@nlpi061.nbdc.sbc.com...
"Ignacio Machin ( .NET/ C# MVP )" <ig************@gmail.comwrote in
message
news:1f**********************************@m44g2000 hsc.googlegroups.com...
>On Aug 5, 12:48 pm, "AliR \(VC++ MVP\)" <A...@online.nospamwrote:
>>Hi everyone,

I have a Socket derived class that parses the received data into a
message,
populates a object with that information and then tries to send an event
to
inform the owner of the socket that there is message to be processed.
But
this is not working as the socket receiver method seems to be in a
different
thread then the form that owns the socket.

The receive callback gets the data from the socket and process the
information, once it constructs a full message from it then it calls a
delegate if the delegate is set.

The method that handles this event needs to change some controls on the
form
and when I do that I get the exception:
Cross-thread operation not valid: Control 'syncButton' accessed from a
thread other than the thread it was created on.

I would appreciate any suggestions on solving this.

class LSSocket : Socket
{
public event ProcessMessageHandler ProcessMessageEvent;

public void OnReceiveData(IAsyncResult)
{
....
if (ProcessMessageEvent != null)
{
ProcessMessageEvent(this, new
ProcessMessageArgs(Msg));
}
}
}

class ProcessMessageArgs : System.EventArgs
{
public ProcessMessageArgs(LSMessage msg)
{
this.msg = msg;
}
public LSMessage msg;
}
delegate void ProcessMessageHandler(object sender,
ProcessMessageArgs
e);

I would have had to use PostThreadMessage in native windows development,
but
I can't figure out what I need to use in this situation.

AliR.

Use Control.Invoke to execute the event in the UI thread.

I looked at Control.Invoke, but wasn't really sure where it would apply.
A little more explanation would be great.

Are you saying that I have to use that in event hander method in my form
class to do the UI manipulation? Or am I supposed to use it in place of
the event hander call? Or am I supposed to call the event handler
delegate using the Invoke method?

Here is the event handler method:
public void ProcessMessage(object sender, ProcessMessageArgs e)
{
switch (e.msg.m_Command)
{
case MSG_SERVERIP: ServerIP = e.msg.m_Address;
ServerPort = 29308;
syncButton.Enabled = true;
break;
default: Debug.Print("Oh Oh");
break;
}
}

AliR
I think I got it. (Correctly or not I don't know.)
Beside the event member, I added a parent form object to the class of type
Control.

delegate void ProcessMessageHandler(LSMessage Msg);
class LSSocket : Socket
{
public event ProcessMessageHandler ProcessMessageEvent;
public Form ParentForm = null;

public void OnReceiveData(IAsyncResult)
{
//pares data into a LSMessage class (Msg)
....
if (ProcessMessageEvent != null && ParentForm != null)
{
// ProcessMessageEvent(this, new
ProcessMessageArgs(Msg));
ParentForm.Invoke(ProcessMessageEvent,Msg);
}
}
.....
}

Hopefully this is the right way of doing it.

AliR.
Aug 5 '08 #4

P: n/a
On Tue, 05 Aug 2008 11:25:58 -0700, AliR (VC++ MVP) <Al**@online.nospam>
wrote:
[...]
public void ProcessMessage(object sender, ProcessMessageArgs e)
{
switch (e.msg.m_Command)
{
case MSG_SERVERIP: ServerIP = e.msg.m_Address;
ServerPort = 29308;
syncButton.Enabled = true;
break;
default: Debug.Print("Oh Oh");
break;
}
}
Try:

public void ProcessMessage(object sender, ProcessMessageArgs e)
{
switch (e.msg.m_Command)
{
case MSG_SERVERIP: ServerIP = e.msg.m_Address;
ServerPort = 29308;
syncButton.Invoke((MethodInvoker)delegate {
syncButton.Enabled = true } );
break;
default: Debug.Print("Oh Oh");
break;
}
}

Not only does that avoid having to track a specific parent control in your
event-raising class, IMHO it's better for the GUI-specific stuff to stay
in the GUI-specific class.

Pete
Aug 5 '08 #5

P: n/a

"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
On Tue, 05 Aug 2008 11:25:58 -0700, AliR (VC++ MVP) <Al**@online.nospam>
wrote:
>[...]
public void ProcessMessage(object sender, ProcessMessageArgs e)
{
switch (e.msg.m_Command)
{
case MSG_SERVERIP: ServerIP = e.msg.m_Address;
ServerPort = 29308;
syncButton.Enabled = true;
break;
default: Debug.Print("Oh Oh");
break;
}
}

Try:

public void ProcessMessage(object sender, ProcessMessageArgs e)
{
switch (e.msg.m_Command)
{
case MSG_SERVERIP: ServerIP = e.msg.m_Address;
ServerPort = 29308;
syncButton.Invoke((MethodInvoker)delegate {
syncButton.Enabled = true } );
break;
default: Debug.Print("Oh Oh");
break;
}
}

Not only does that avoid having to track a specific parent control in your
event-raising class, IMHO it's better for the GUI-specific stuff to stay
in the GUI-specific class.

Pete
Very cool, thank you. I had no idea how to use Invoke! As you can tell
I'm a newbee.

AliR.
Aug 5 '08 #6

P: n/a
On Aug 5, 2:25 pm, "AliR \(VC++ MVP\)" <A...@online.nospamwrote:
"Ignacio Machin ( .NET/ C# MVP )" <ignacio.mac...@gmail.comwrote in
messagenews:1f**********************************@m 44g2000hsc.googlegroups.com...
On Aug 5, 12:48 pm, "AliR \(VC++ MVP\)" <A...@online.nospamwrote:
Hi everyone,
I have a Socket derived class that parses the received data into a
message,
populates a object with that information and then tries to send an event
to
inform the owner of the socket that there is message to be processed.
But
this is not working as the socket receiver method seems to be in a
different
thread then the form that owns the socket.
The receive callback gets the data from the socket and process the
information, once it constructs a full message from it then it calls a
delegate if the delegate is set.
The method that handles this event needs to change some controls on the
form
and when I do that I get the exception:
Cross-thread operation not valid: Control 'syncButton' accessed from a
thread other than the thread it was created on.
I would appreciate any suggestions on solving this.
class LSSocket : Socket
{
public event ProcessMessageHandler ProcessMessageEvent;
public void OnReceiveData(IAsyncResult)
{
....
if (ProcessMessageEvent != null)
{
ProcessMessageEvent(this, new
ProcessMessageArgs(Msg));
}
}
}
class ProcessMessageArgs : System.EventArgs
{
public ProcessMessageArgs(LSMessage msg)
{
this.msg = msg;
}
public LSMessage msg;
}
delegate void ProcessMessageHandler(object sender, ProcessMessageArgs
e);
I would have had to use PostThreadMessage in native windows development,
but
I can't figure out what I need to use in this situation.
AliR.
Use Control.Invoke to execute the event in the UI thread.

I looked at Control.Invoke, but wasn't really sure where it would apply. A
little more explanation would be great.

Are you saying that I have to use that in event hander method in my form
class to do the UI manipulation?
Yes, in windows forms the controls should only be accessed from the
UI thread. You can make an event to be executed in the UI thread (or
more exactly in the control's creation thread, that in the current
implementation is the UI) by using Control.Invoke.

Invoke what does is put a message in the message pump that will be
executed as any other message in a win. app.
Aug 5 '08 #7

This discussion thread is closed

Replies have been disabled for this discussion.