Hi, I’m new to C# and I’m having a problem trying to notify the main thread from a worker thread.
My app has to periodically check (say every 10 secs) if it is connected to a server. To do this I’ve used a timer. As I understand, every 10 secs the timer executes the method CheckConnection (and this is done with a pooled thread). In CheckConnection I want to check if I’m connected to a particular server, if I’m not (i.e. server has gone down) I want to somehow notify the main thread and get the main thread to execute the DealWithServerDown method. I’ve seen lots of examples of this kind of problem, but it’s always using Forms. My solution needs to work for both console and GUI apps.
Any help would be REALLY appreciated. Thanks for looking!
using System;
using System.Threading;
class Program
{
static void Main()
{
Timer tmr = new Timer (CheckConnection, "Checking...", 10000,10000);
Console.ReadLine();
tmr.Dispose(); // End the timer
}
static void CheckConnection (object data)
{
// This runs on a pooled thread
Console.WriteLine (data);
// Check if connected to network here
if( notConnected)
{
// Notify main thread that it needs to call the DealWithServerDown method
// Set timer interval to not check again
}
}
public void DealWithServerDown()
{
// Main thread to execute this
}
}
David ChristopherPosted Dec 17, 2007, 3:57 AM
Hi Mike,
Thanks for your reply. You're right I could do it that way. What I wanted to do though was send a message from the worker thread to the main thread to notify it rather than forcing the main thread to check a boolean periodically. However, I've since learned that with console apps there is no message pump, and therefore I can't send a message to the main thread. So the only way around it is as you described.
Cheers
Mike GoldPosted Dec 10, 2007, 12:18 PM
Judging from your original post, all you have to do is set a boolean in the main thread to tell it to call DealWithServer. Every time the server runs through the timer it will check the boolean, if it is set, it will call DealWithServer. The boolean can be set from any thread. (If you make the boolean static, you can just set it at the class level. Remember to turn the flag off when you are done with the execution. and lock the critical section so you don't get a race condition
lock {}
David ChristopherPosted Dec 10, 2007, 9:34 AM
Hi,
Thanks for your reply. The main thread could be doing absolutely anything, depending on what the user has done. Or it could be doing nothing. However, I have since found out that what I wanted to do is actually not possible. I've since discovered that with console apps there is no message pump, and hence you can't queue messages. This is why the above problem is trivial with GUI, where the message pump is generated following Application.Run etc.
Thanks for your replies...........
Dr SpackPosted Dec 9, 2007, 2:21 PM
I am sorry that I didn't fully understand your original question. But now I've got you!
As you stated it is quite easy to make an invokation to the gui-thread.
But before we can make a call to an other thread we have to know what the other thread is doing or is not doing. Is it working or is it waiting for something?
When it is working, then I don't think that you can interrupt that thread, let him execute the DealWithServerDown-Method and then return to the orignal work. So maybe you can set a flag that you can check and then call that funktion?
Can you tell me what this main thread does?
David ChristopherPosted Dec 7, 2007, 10:55 AM
Hi,
I tried your suggestion but the DealWithServerDown function is still being executed by the worker thread. This has to work for both GUI and console apps so I can't use Control.Invoke as there is no control in the console app. Surely there must be someway for the worker thread (i.e. the timer) to notify the main thread (i.e post a message) to get the main thread to execute the DealWithServerDown method.
I'm really puzzled on this one!!!!
Thanks.................
David ChristopherPosted Dec 7, 2007, 5:10 AM
Dr SpackPosted Dec 6, 2007, 12:34 PM
my idea is to just pass an callback function through the state parameter (instead of the string Checking..." )
public delegate void ServerIsDisconnectedDelegate();
// ...snipp
Timer tmr = new Timer (CheckConnection, new ServerIsDisconnectedDelegate( DealWithServerDown ), 10000, 10000);
// ... snapp
static void CheckConnection (object data)
{
// This runs on a pooled thread
//Console.WriteLine (data);
// Check if connected to network here
if( notConnected)
{
ServerIsDisconnectedDelegate dealWithServerDownCallback = data as ServerIsDisconnectedDelegate;
if( dealWithServerDownCallback != null )
dealWithServerDownCallback();
else
{
// Uopsss?
}
}
}
And keep in mind that you have to deal with CrossThreadExceptions when you using windows control. Hint: Control.InvokeRequierd...