activating windows from a separate thread

S

Steve Sargent

Hi:

I'm running a chat application that when called by a remote caller, opens a chat window. Currently,
I'm using Application.Run() to create each new window, because I am having problems accessing the
window from the non-gui thread. However, I imagine this is very resource intensive, and would
rather find a cleaner approach, if possible.

In testing possible scenarios, I've noted that a form instantiated inside the constructor of the
main window can be called (invoked, actually) from a different thread....if it has already been
shown before. By that, I mean if a call to show has been placed on the child form from the parent's
gui thread, then subsequent calls work out fine. In debugging, I noted that if the form hasn't
already been shown, then the first InvokeRequired call to the form comes back as false. Obviously,
this isn't true, since I do need to view the form from the thread that instantiated it.

I've tried tricks to get around this with no avail. I've set a flag up so that the first time Load
is called from the child form, it's visible flag is set to false. I've done the same with calling
hide the first time; i've combined the two. I've called Close on them (which has cancel set to true
and hide set). Then I've called them first from the parent's constructor with Show(). They child
window doesn't hide.

I've tried calling invoke directly without testing...I get an exception because the window hasn't
been created yet.

I'm running out of options.

The only other option I can think of right now is to setup an invisible button and invoke it, which
will show the window. I think....that would work...I don't know, though. I've always had problems
for some reason with the button.PerformClick() method.

Does anyone have any suggestions on ways to get the gui to do its loadup stuff without displaying
the child window, so I can call the child window from another thread safely?

Any help given is greatly appreciated.

Steve
 
G

Guest

It seems to me that maybe there's a problem with your architecture...

I'm assuming you're doing something like MSN Messenger or other IM chat
programs where you have your main contacts window and multiple chat windows.

First of all, there's no need to use threading ANYWHERE.

You can have multiple forms open and operating simultaneously (handling
events and so forth) as long as they're modeless. Remember, Windows uses a
message loop underneath, so you can use that and a combination of
asynchronous sockets to keep your app from blocking on socket calls. I think
you'll find this is much easier to manage than trying to deal with multiple
threads and multiple apps.

Let each form have its own socket for communication and handle the receive
events for receiving information and displaying the information in the form.
All of this can happen in a single application thread.

Pete

Steve Sargent said:
Hi:

I'm running a chat application that when called by a remote caller, opens a chat window. Currently,
I'm using Application.Run() to create each new window, because I am having problems accessing the
window from the non-gui thread. However, I imagine this is very resource intensive, and would
rather find a cleaner approach, if possible.

In testing possible scenarios, I've noted that a form instantiated inside the constructor of the
main window can be called (invoked, actually) from a different
thread....if it has already been
 
S

Stoitcho Goutsev \(100\) [C# MVP]

The problem is that when you create a comonent class it doesn't create the
underlying Windows control right away. So it is possible that when you call
some method or access some property on the form form the working thread then
the Windows control gets created in the context of this thread. The
Windows controls not the .NET classes are the ones that cannot be used form
different threads.

However you cannot parent controls created from different threads.
--

Stoitcho Goutsev (100) [C# MVP]


Steve Sargent said:
Hi:

I'm running a chat application that when called by a remote caller, opens a chat window. Currently,
I'm using Application.Run() to create each new window, because I am having problems accessing the
window from the non-gui thread. However, I imagine this is very resource intensive, and would
rather find a cleaner approach, if possible.

In testing possible scenarios, I've noted that a form instantiated inside the constructor of the
main window can be called (invoked, actually) from a different
thread....if it has already been
 
S

Steve Sargent

I haven't been doing this that long, so I apologize if I'm not understanding all of what you are
saying.


At the moment, I'm not sure how I could do this without additional threads. Mainly in fact because
I'm using remote objects, rather than direct sockets. Although I know there are underlying sockets
with remoting, I don't know how to access the listening threads directly to do that.

Obviously, if I am the one choosing to setup a chat window with a remote user, I can access the
window directly through the gui event handler; but on the other side, when they receive a request, I
don't know how they are to control which thread receives the remote function call.

The application was/is an attempt to do client/server apps using remote objects. At the moment, as
said earlier, I cannot access the chat windows because the InvokeRequired returns false, since I
haven't called Show() on the chat windows (I'm assuming that's why, actually), and the windows
havent' been fully created. It's like I'm stuck between threads. I can't call invoke, but I can't
call Show() either, since I'm not in the gui thread.

Anyhow, thanks for the response. If you know of ways to direct the remote functions to be called
within the gui thread, I'd love the helpful advice.


Thanks

Steve
 
G

Guest

Steve,

No need to apologize, you have to learn this stuff somehow.

This can still be handled without additional threads if you have access to
both the client and server code.

Instead of polling for a response (i.e. calling a method like GetResponse()
or whatever it's called) for retrieving incoming messages, use an event in
the remote object which will activate when there's a response.

Can you give me an idea for how it works? I mean, do you do something like:

remoteObject.SendMessage(myMessageString)
remoteString = remoteObject.ReceiveMessage();

where the ReceiveMessage() waits for a response from the remote object?

Instead you could create an event on the remote object called say,
MessageReady. When a message is sent to remoteObject it, I assume, somehow
figures out who the recipient is. It could then trigger the MessageReady
event for that recipient with the event parameter carrying the message.

This way you still don't need threads.

Pete

Steve Sargent said:
I haven't been doing this that long, so I apologize if I'm not
understanding all of what you are
saying.


At the moment, I'm not sure how I could do this without additional
threads. Mainly in fact because
 
S

Steve Sargent

Thanks.

I'll give a brief on what goes on right now. I'll add additional code (although if shown in
public, I must deny my involvement with it adamantly :) .

Right now, I have to remote objects -- chat monitors - that handle the main connection stuff.

In my online area, I'll select the other member, and click the chat button. chat button calls
another thread for the work to setup connection (this thread could be removed to keep it in the gui
thread; but would only provide half a solution).

In the tree, each other member has an associated chatmonitor hooked in the target of the tree node.
So, in the chat handler thread, I call my own chat monitor, passing it in the remote monitor object
as a reference. The local monitor then contacts the remote monitor via asynchronous remote method
call to establish a connection. The remote computer's chat monitor then signals its application,
through a callback method, to establish a chat window, giving the application a link to a local chat
node (remote object that handles calls between users) that is connected to the remote chat node (my
local chat node; passed as parameter when my chat monitor calls the remote monitor). Once the
callback routine successfully sets up a window to handle chat messages, it returns control to the
chat monitor, who signals the chat node that the connection is ready. Then it returns to the
calling chat monitor, who, in turn also calls its callback, sets up it's chat window with a local
chat node, and etc.... I'll attach a snippet with code from the key components to see what I mean.

From my side, I could easily get rid of the chat handler thread and just do this inside of the gui
thread; or, at least the part of the contacting the callback. That would work, since then the
window would be created in the gui thread.

The problem is on the standpoint of the remote caller. If someone invokes my chat monitor to
startup a chat session, it will be in its own thread (from what I understand, since the call is
made asynchronously, it will be part of the thread pool). This is where my problem lies. How do I
setup the chat window from here? Since all my chat windows are instantiated, but not yet loaded (at
least, on the first run through), I can't access them. InvokeRequired returns false, yet a direct
Show() command fails.


Thanks again for the help.

Steve
 

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