.NET Forum / .NET Framework / New Users / June 2007
C# threading, events and main thread.
|
|
Thread rating:  |
djdouma - 16 Jun 2007 13:38 GMT I've been working on this one for a couple of days, and am completly at my wits end. Is there some method for executing a function or event in the main thread, when called from a 'worker' thread? I understand how it works in the Windows forms world, but what about an application with no GUI?
I provided example code and the output below. What I'm looking for is to have the prog_ShowPopUpEvent method executed by the main thread.
Thanks!
Output: MAIN THREAD : Sleeping for 1 second MAIN THREAD : Sleeping for 1 second MAIN THREAD : Sleeping for 1 second MAIN THREAD : Sleeping for 1 second MAIN THREAD : Sleeping for 1 second TIMER THREAD : timer elapsed TIMER THREAD : fire show pop up event TIMER THREAD : show pop up event fired Main thread exiting.
Code: using System; using System.Threading;
namespace ConsoleApplication1 { public class Program { private bool _running = false; private event EventHandler ShowPopUpEvent;
[STAThread] public static void Main() { Program prog = new Program(); prog.Run(); }
private void Run() { this.ShowPopUpEvent += new EventHandler(prog_ShowPopUpEvent); Thread.CurrentThread.Name = "MAIN THREAD";
System.Timers.Timer checksTimer = new System.Timers.Timer();
//Elapse every 5 seconds checksTimer.Interval = 5000; checksTimer.Elapsed +=new System.Timers.ElapsedEventHandler(checksTimer_Elapsed); checksTimer.Enabled = true;
this._running = true;
do { Console.WriteLine("{0} : Sleeping for 1 second", Thread.CurrentThread.Name); Thread.Sleep(1000); } while (this._running); Console.WriteLine("Main thread exiting."); }
private void prog_ShowPopUpEvent(object sender, EventArgs e) { Console.WriteLine("{0} : show pop up event fired", Thread.CurrentThread.Name); this._running = false; }
void checksTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (Thread.CurrentThread.Name == null) Thread.CurrentThread.Name = "TIMER THREAD";
Console.WriteLine("{0} : timer elapsed", Thread.CurrentThread.Name);
//Perform a bunch of checks if (true == false) { } else { //Show the popup window OnShowPopup(); } }
private void OnShowPopup() { if (ShowPopUpEvent != null) { Console.WriteLine("{0} : fire show pop up event", Thread.CurrentThread.Name); ShowPopUpEvent(this, new EventArgs()); } } } }
Peter Duniho - 16 Jun 2007 18:23 GMT > I've been working on this one for a couple of days, and am completly > at my wits end. Is there some method for executing a function or > event in the main thread, when called from a 'worker' thread? Yes. Use the Control.Invoke() method.
I don't know what version of Visual Studio you're using, if any, but I'm using VS 2005 and if I tried to execute the code you posted, I'd get the "cross-thread call" MDA exception, with a clickable link to a help topic that provides very nice details regarding how to do this.
Pete
Jon Skeet [C# MVP] - 16 Jun 2007 19:16 GMT > > I've been working on this one for a couple of days, and am completly > > at my wits end. Is there some method for executing a function or > > event in the main thread, when called from a 'worker' thread? > > Yes. Use the Control.Invoke() method. There are no controls to invoke in this case though - it's a console application.
> I don't know what version of Visual Studio you're using, if any, but I'm > using VS 2005 and if I tried to execute the code you posted, I'd get the > "cross-thread call" MDA exception, with a clickable link to a help topic > that provides very nice details regarding how to do this. No, you wouldn't - that applies to Windows Forms, not console applications.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Peter Duniho - 16 Jun 2007 19:33 GMT > No, you wouldn't - that applies to Windows Forms, not console > applications. Are you trying to tell me that I should not be trying to answer questions after staying up almost all night with a sick kid?
Sheesh...picky, picky.
(Yes, I completely missed the fact that this is a console application...sorry)
Jon Skeet [C# MVP] - 16 Jun 2007 19:42 GMT > > No, you wouldn't - that applies to Windows Forms, not console > > applications. > > Are you trying to tell me that I should not be trying to answer questions > after staying up almost all night with a sick kid? LOL.
> Sheesh...picky, picky. > > (Yes, I completely missed the fact that this is a console > application...sorry) If I had to pay someone every time I'd come up with a bad answer for whatever reason, I'd be on the street...
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Ben Voigt [C++ MVP] - 16 Jun 2007 19:47 GMT >> > No, you wouldn't - that applies to Windows Forms, not console >> > applications. [quoted text clipped - 11 lines] > If I had to pay someone every time I'd come up with a bad answer for > whatever reason, I'd be on the street... So would I. In fact, isn't that the true meaning of "MVP"?
Jon Skeet [C# MVP] - 16 Jun 2007 19:17 GMT > I've been working on this one for a couple of days, and am completly > at my wits end. Is there some method for executing a function or > event in the main thread, when called from a 'worker' thread? I > understand how it works in the Windows forms world, but what about an > application with no GUI? You'd need to have your own equivalent of the message pump - basically the main thread would just have to be waiting to be given work to do. You can't interrupt a running thread to give it a different task.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Ben Voigt [C++ MVP] - 16 Jun 2007 19:34 GMT >> I've been working on this one for a couple of days, and am completly >> at my wits end. Is there some method for executing a function or [quoted text clipped - 5 lines] > the main thread would just have to be waiting to be given work to do. > You can't interrupt a running thread to give it a different task. So the key question is, what is the main thread doing when you want to give it a function to execute? Can you have it periodically poll a list of delegates (don't forget locking, or use a thread-safe linked list)?
djdouma - 17 Jun 2007 04:04 GMT > "Jon Skeet [C#MVP]" <s...@pobox.com> wrote in messagenews:MPG.20de3985ba15021724b@msnews.microsoft.com... > [quoted text clipped - 18 lines] > > - Show quoted text - I suppose the main thread could poll a list of delegates to see if it has work to do. Would you be able to provide a sample of this? Would the delegate list just be using an ArrayList or a typed List<T>? I was looking for similar functionality to the Invoke / BeginInvoke used in Windows Forms. The reason for the do while with a sleeping thread is just so the application doesn't exit. :D The timer checks if certian conditions have exist (Certian reg values to exist, files to exist, etc), and notify the main thread. The main thread will then respond according to the condition that was met. In some cases, it may need to display a pop-up, in others, it may need to start a process.
Ben Voigt [C++ MVP] - 17 Jun 2007 04:15 GMT >> "Jon Skeet [C#MVP]" <s...@pobox.com> wrote in >> messagenews:MPG.20de3985ba15021724b@msnews.microsoft.com... [quoted text clipped - 31 lines] > may need to display a pop-up, in others, it may need to start a > process. Use an Event to wake the main thread after adding to the list, instead of polling.
I would certainly recommend using a generic LinkedList<T>. ArrayList is the best that could be done in C# 1.0, since C# 2.0 came out the generic collections are better in every way. Or you could just use a delegate variable with the += operator.
Surround all access to the delegate list with a lock block for thread-safety... you can lock on the list if you use a LinkedList, or on typeof(MyMainClass) if using a static delegate variable.
Peter Duniho - 17 Jun 2007 18:59 GMT > I suppose the main thread could poll a list of delegates to see if it > has work to do. Would you be able to provide a sample of this? Would > the delegate list just be using an ArrayList or a typed List<T>? I > was looking for similar functionality to the Invoke / BeginInvoke used > in Windows Forms. Ben has given good suggestions for how to implement this yourself. There's nothing built in to .NET that provides for this directly, a la Invoke().
> The reason for the do while with a sleeping thread > is just so the application doesn't exit. :D The timer checks if [quoted text clipped - 3 lines] > may need to display a pop-up, in others, it may need to start a > process. In addition to what Ben wrote, regarding implementing a delegate queue, your reply begs the question: if all the main thread is doing is waiting for some other thread to do work, why not just do the work on the main thread?
Basically, we can answer the question (and Ben has) of how to accomplish the very specific goal stated (have one thread pass a delegate to another thread for execution). But it still appears that there's no need to do that. It's not usually necessary for a given piece of code to execute on a particular thread, and it's not clear what it is that the main thread in your application is doing that prevents it from simply being the thread to do whatever the other thread is doing anyway.
It seems to me that there are two open questions yet:
1) Why can't the code running on the worker thread simply be executed in the main thread?
2) Why can't the code that you want executed on the main thread just be executed in the worker thread?
You don't have to answer these question here, of course. But if you want the best advice, you should. And at a minimum, you should at least consider them with respect to the design of your code, because on the face of it there are some odd things about the design of your code, at least based on the small peek we have gotten of it.
Pete
Peter Duniho - 16 Jun 2007 19:42 GMT > I've been working on this one for a couple of days, and am completly > at my wits end. Is there some method for executing a function or > event in the main thread, when called from a 'worker' thread? I > understand how it works in the Windows forms world, but what about an > application with no GUI? For what it's worth, now that I have been directed back onto the correct track...
Can you explain in more detail _why_ you want the handling of the event to occur on the main thread? The reason this is such a big deal with a Form is because of the restrictions Windows has with respect to windows and their relationship to the thread that created a window. But as far as I know, there's not a similar issue with the console output.
(In my defense, it's this lack of an issue with respect to console applications, as well as the "ShowPopUp" name of your event handler, that made me assume you were talking about Forms even though you specifically said you weren't).
Pete
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|