C# Newbie has threading problem...

C

Christian Stapfer

I am in the process of porting a Java program
(a distributed whiteboard) to C# that reads
messages from a socket, and hands received
messages to a Windows Form.
It is multithreaded: let me call the thread
that handles the network side the "networking
thread".
Since I am not allowed to call members of
a Windows control directly from the networking
thread, I use Invoke with an appropriate delegate.
Unfortunately, the received messages does not
get to the GUI thread / the Windows control, and
I cannot figure out why.

What happens, in sequence, is the following:

// 1. When the networking thread has received a
// message (in member Demux() of a GenericClient
// object), it creates a *new* MemoryStream for
// that message, and wraps it in a BinaryReader
// like this:

BinaryReader
reader = new BinaryReader(
new MemoryStream(byteArrayIn.ToArray()));

// 2. then it invokes the client', like this:

client.Receive(reader);

// 3. However, this 'client' is not yet the real client
// (i.e. the Windows Form that is to receive the message)
// but a wrapper class (SyncClient), that uses Invoke
// to call the Receive-member of the Windows Form with
// the same signature, like this:

public void Receive(BinaryReader dataIn)
{
((Control)client).Invoke(rd, dataIn);
}

// where rd has been initialized like this:
delegate void ReceiveDelegate(BinaryReader dataIn);
rd = new ReceiveDelegate(client.Receive);

// 4. But the Receive member of the Windows Form
// (MainForm, client.Receive) receives no data
// at all, when the GUI thread subsequently
// executes it: the memory stream it gets is
// empty.
// I can see this in the debugger, and when I
// insert Console.WriteLine statements to dump
// the current length of the message, like this:

Console.WriteLine("<Class>.<Member>(): Invoking client.Receive() with Length
== "+dataIn.BaseStream.Length);

// I get the following output:

GenericClient.Demux(): Invoking client.Receive() with Length == 18
SyncClient.Receive(): Invoking client.Receive() with Length == 18
MainForm.Receive(): Receiving Length == 0

In other words: the message mysteriously disappears
between the Invoke-statement in the SyncClient,
and the actual execution of the invoked member of
the MainForm: the MemoryStream goes from Length==18
to Length==0!

Now, since this is multithreading, I would not be
surprised at all by such an occurrence, *if* it
were not for the fact that a *new* MemoryStream
had been created by the networking thread for the
express purpose of holding the received message,
so that it can be handed over to the Windows
Form *completely*untouched* (or so I had thought)
by *any* further (asynchronous) actions by the
networking thread.

If you have an idea about what might be the
cause of this problem, I would be very glad indeed
to hear from you ;-)

Thanks in advance,
Christian
 
C

Christian Stapfer

Christian Stapfer wrote:

<snip/>

The only idea that I have left is that the Windows
Form's Receive member has not been invoked appropriately
(i.e. it gets a garbage dataIn parameter that only
looks like a Binary Reader - but if so, could it read
its Lenght property? - I'd think it could not do that...)
But how can the delegate I use for this purpose
(as defined below) have the wrong signature? - The
compiler surely checks the signature when I try
to construct a new ReceiveDelegate object:
public void Receive(BinaryReader dataIn)
{
((Control)client).Invoke(rd, dataIn);
}

// where rd has been initialized like this:
delegate void ReceiveDelegate(BinaryReader dataIn);
rd = new ReceiveDelegate(client.Receive);
^^^^^^^^^^^^^^
The signature cannot be wrong - or can it?

That I might do something wrong in my *first*
use of delegates and Control.Invoke() is very
likely. - The problem is: I do not see (even
after sleeping over it) where I have made
one more stupid mistake....

Regards,
Christian
 
C

Christian Stapfer

I have solved this problem (my mistake: I did not
even notice a small but crucial hack that I had
inserted when the Receive() method still was a
mere stub...)

Regards, and sorry for any inconvenience that
by question may have caused,

Christian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top