473,387 Members | 1,501 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Problem implementing a message loop

I am trying to write an event-driven application with no main window that
runs "forever". It waits on a named event and then displays a window
depending on data pased in a memory-mapped file. I started with a standard
console application and it all works fine, except that it does not terminate
tidily when the user logs off/shuts down. So, I figured I needed a message
loop to pick up WM_QUIT. I studied the code in "Waiting in a message loop"
(http://msdn.microsoft.com/library/de...ssage_loop.asp) and implemented it in my Main(), using
MsgWaitForMultipleObjects(1, handles, false, INFINITE, QS_POSTMESSAGE +
QS_SENDMESSAGE);
to wait for either my named event (in 'handles') or a windows message. The
event fires fine, but no windows messages ever arrive. I am obviously doing
something wrong, Can anyone advise.
--
Dave
May 29 '06 #1
8 5230

"Dave" <Da**@discussions.microsoft.com> wrote in message
news:21**********************************@microsof t.com...
|I am trying to write an event-driven application with no main window that
| runs "forever". It waits on a named event and then displays a window
| depending on data pased in a memory-mapped file. I started with a standard
| console application and it all works fine, except that it does not
terminate
| tidily when the user logs off/shuts down. So, I figured I needed a message
| loop to pick up WM_QUIT. I studied the code in "Waiting in a message loop"
|
(http://msdn.microsoft.com/library/de...ssage_loop.asp)
and implemented it in my Main(), using
| MsgWaitForMultipleObjects(1, handles, false, INFINITE, QS_POSTMESSAGE +
| QS_SENDMESSAGE);
| to wait for either my named event (in 'handles') or a windows message. The
| event fires fine, but no windows messages ever arrive. I am obviously
doing
| something wrong, Can anyone advise.
| --
| Dave

This will not work, you need a main windows for the system to post/send
messages to, you just need to handle the SessionEnded event on the
Microsoft.Win32.SystemEvents class.

Willy.
May 29 '06 #2
Thanks Willy, but if I implement it as a Windows app with a main window,
execution then disappears into the main window (ie the main window's message
loop) so how do I then wait for my named event?
--
Dave
"Willy Denoyette [MVP]" wrote:

"Dave" <Da**@discussions.microsoft.com> wrote in message
news:21**********************************@microsof t.com...
|I am trying to write an event-driven application with no main window that
| runs "forever". It waits on a named event and then displays a window
| depending on data pased in a memory-mapped file. I started with a standard
| console application and it all works fine, except that it does not
terminate
| tidily when the user logs off/shuts down. So, I figured I needed a message
| loop to pick up WM_QUIT. I studied the code in "Waiting in a message loop"
|
(http://msdn.microsoft.com/library/de...ssage_loop.asp)
and implemented it in my Main(), using
| MsgWaitForMultipleObjects(1, handles, false, INFINITE, QS_POSTMESSAGE +
| QS_SENDMESSAGE);
| to wait for either my named event (in 'handles') or a windows message. The
| event fires fine, but no windows messages ever arrive. I am obviously
doing
| something wrong, Can anyone advise.
| --
| Dave

This will not work, you need a main windows for the system to post/send
messages to, you just need to handle the SessionEnded event on the
Microsoft.Win32.SystemEvents class.

Willy.

May 29 '06 #3

"Dave" <Da**@discussions.microsoft.com> wrote in message
news:C1**********************************@microsof t.com...
| Thanks Willy, but if I implement it as a Windows app with a main window,
| execution then disappears into the main window (ie the main window's
message
| loop) so how do I then wait for my named event?
| --
| Dave
|
|
| "Willy Denoyette [MVP]" wrote:
|

Sorry if I wasn't clear, point is that you don't need a main windows (a Form
instance), all you need is a message pump to handle this.
You can start a separate thread to handle your main task before you start
the message loop by calling Application.Run().

Something like this should do:
[STAThread]
static void Main()
{
SystemEvents.SessionEnded += new
SessionEndedEventHandler(SessionEnd);
// Start a new backgound thread to handle your main task here.
// Start a message pump.
Application.Run();
}
static void SessionEnd(object s, SessionEndedEventArgs e)
{
...
}

Willy.
May 29 '06 #4
Hi Willy
I was confused there as your original reply said "you need a main windows".
I have implemented the event (I used SessionEnding rather than SessionEnded)
but it still doesn't work - when I log off the SessionEnding event is never
fired, but I get a window ".NET-Broadcast Event Window 1.0.5 - This program
is not responding" etc. I would guess that this is because I am not calling
Application.Run because I need to run my own loop waiting for my named event.
Any further suggestions gratefully received. (Maybe I need to make it a
Windows application and override WndProc?)

BTW there seem to be a lot of problems with the newsgroups at the moment.
The "read the response" links in the notification emails haven't worked for
weeks, and 9 times out of 10 I get "page does not exist" when I try to access
a newsgroup. Can you pass the message on to MS.
--
Dave
"Willy Denoyette [MVP]" wrote:

"Dave" <Da**@discussions.microsoft.com> wrote in message
news:C1**********************************@microsof t.com...
| Thanks Willy, but if I implement it as a Windows app with a main window,
| execution then disappears into the main window (ie the main window's
message
| loop) so how do I then wait for my named event?
| --
| Dave
|
|
| "Willy Denoyette [MVP]" wrote:
|

Sorry if I wasn't clear, point is that you don't need a main windows (a Form
instance), all you need is a message pump to handle this.
You can start a separate thread to handle your main task before you start
the message loop by calling Application.Run().

Something like this should do:
[STAThread]
static void Main()
{
SystemEvents.SessionEnded += new
SessionEndedEventHandler(SessionEnd);
// Start a new backgound thread to handle your main task here.
// Start a message pump.
Application.Run();
}
static void SessionEnd(object s, SessionEndedEventArgs e)
{
...
}

Willy.

May 30 '06 #5
Dave <Da**@discussions.microsoft.com> wrote:
I was confused there as your original reply said "you need a main windows".
I have implemented the event (I used SessionEnding rather than SessionEnded)
but it still doesn't work - when I log off the SessionEnding event is never
fired, but I get a window ".NET-Broadcast Event Window 1.0.5 - This program
is not responding" etc. I would guess that this is because I am not calling
Application.Run because I need to run my own loop waiting for my named event.
Any further suggestions gratefully received. (Maybe I need to make it a
Windows application and override WndProc?)


I've tested this application and it works for me:

---8<---
using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;

class App
{
static void Main()
{
EventWaitHandle closing = new ManualResetEvent(false);
bool running = true;

SystemEvents.SessionEnded += delegate
{
running = false;
closing.Set();
File.WriteAllText("\\Log.txt", "Session ended");
};

Thread worker = new Thread((ThreadStart)delegate
{
for (;;)
{
WaitHandle.WaitAny(new WaitHandle[] { closing
/* , X, etc. */ });
if (!running)
break;

// Do work because of event X or whatever
}
File.WriteAllText("\\Closed.txt", "Success!");
});
worker.Start();

Application.Run();
}
}
--->8---

Perhaps you can adapt your application along these lines?

-- Barry

--
http://barrkel.blogspot.com/
May 30 '06 #6
Dave <Da**@discussions.microsoft.com> wrote:
I would guess that this is because I am not calling
Application.Run because I need to run my own loop waiting for my named event.
Any further suggestions gratefully received.


I should point out that each thread is separate as far as message loops
are concerned. You can call Application.Run() on the main thread so that
the session ended event occurs, and create your own message loop (or
call Application.Run() again) on a different thread, without problems.

-- Barry

--
http://barrkel.blogspot.com/
May 30 '06 #7
Are you sure you compiled as a Windows application? Console applications
cannot receive Session ending messages.

Consider following sample to get you started.

public class Program
{
static int keepRunning;
[STAThread]
static void Main()
{
Program prog = new Program();
// Optionally install a tray icon and attached context memu
prog.InitializeTray();
Interlocked.Exchange(ref keepRunning, 1);
Thread t = new Thread(new ThreadStart(prog.ThreadJob));
t.Start();
// Register handler
SystemEvents.SessionEnding += new
SessionEndingEventHandler(prog.SessionEnd);
// Start the message loop, this one creates a parking window and
associated message queue,
// windows messages will be posted to this queue.
Application.Run();
}
void ThreadJob()
{
// Initialize thread invariants like synchronization handles
// ...
// keep running the loop until requested to terminate
while (Interlocked.Exchange(ref keepRunning, 1) == 1)
{
// this is your task loop, make sure you don't start blocking
operations in this loop, start another thread when needed.
}
// Clean-up thread invariants here
}
void InitializeTray()
{
// Initialize context menu
MenuItem cntxtMenuItem = new MenuItem();
cntxtMenuItem.Index = 0;
cntxtMenuItem.Text = "E&xit";
cntxtMenuItem.Click += new System.EventHandler(this.cntxtMenu_Click);
ContextMenu cntxtMenu = new ContextMenu();
cntxtMenu.MenuItems.AddRange(
new MenuItem[] {cntxtMenuItem});
// Attach context menu to notifyIcon
NotifyIcon notifyIcon;
notifyIcon = new NotifyIcon();
notifyIcon.Icon = new System.Drawing.Icon(@"whatever.ico");
notifyIcon.Visible = true;
notifyIcon.Text = "My program";
notifyIcon.ContextMenu = cntxtMenu;
}
void cntxtMenu_Click(object Sender, EventArgs e) {
Interlocked.Exchange(ref keepRunning, 0); // Ask threads to terminate
Application.Exit(); // exit application
}

void SessionEnd(object s, SessionEndingEventArgs e)
{
// signal auxiliary thread(s) to stop
Interlocked.Exchange(ref keepRunning, 0);
// cleanup program invariants when needed (constrained by session
end time-out)
//...
// and accept session to end
e.Cancel = true;
}
}
}
}

Willy.
PS. Can't help you with your newsreader issue, apparently you aren't using a
NNTP newsreader (and posting host), I suggest you try another posting host
and/or reader.

"Dave" <Da**@discussions.microsoft.com> wrote in message
news:7F**********************************@microsof t.com...
| Hi Willy
| I was confused there as your original reply said "you need a main
windows".
| I have implemented the event (I used SessionEnding rather than
SessionEnded)
| but it still doesn't work - when I log off the SessionEnding event is
never
| fired, but I get a window ".NET-Broadcast Event Window 1.0.5 - This
program
| is not responding" etc. I would guess that this is because I am not
calling
| Application.Run because I need to run my own loop waiting for my named
event.
| Any further suggestions gratefully received. (Maybe I need to make it a
| Windows application and override WndProc?)
|
| BTW there seem to be a lot of problems with the newsgroups at the moment.
| The "read the response" links in the notification emails haven't worked
for
| weeks, and 9 times out of 10 I get "page does not exist" when I try to
access
| a newsgroup. Can you pass the message on to MS.
| --
| Dave
|
|
| "Willy Denoyette [MVP]" wrote:
|
| >
| > "Dave" <Da**@discussions.microsoft.com> wrote in message
| > news:C1**********************************@microsof t.com...
| > | Thanks Willy, but if I implement it as a Windows app with a main
window,
| > | execution then disappears into the main window (ie the main window's
| > message
| > | loop) so how do I then wait for my named event?
| > | --
| > | Dave
| > |
| > |
| > | "Willy Denoyette [MVP]" wrote:
| > |
| >
| > Sorry if I wasn't clear, point is that you don't need a main windows (a
Form
| > instance), all you need is a message pump to handle this.
| > You can start a separate thread to handle your main task before you
start
| > the message loop by calling Application.Run().
| >
| > Something like this should do:
| >
| >
| > [STAThread]
| > static void Main()
| > {
| > SystemEvents.SessionEnded += new
| > SessionEndedEventHandler(SessionEnd);
| > // Start a new backgound thread to handle your main task here.
| > // Start a message pump.
| > Application.Run();
| > }
| > static void SessionEnd(object s, SessionEndedEventArgs e)
| > {
| > ...
| > }
| >
| > Willy.
| >
| >
| >
May 30 '06 #8
Brilliant. Thanks Barry, that gave me the clue I needed. All works fine now.
--
Dave
"Barry Kelly" wrote:
Dave <Da**@discussions.microsoft.com> wrote:
I was confused there as your original reply said "you need a main windows".
I have implemented the event (I used SessionEnding rather than SessionEnded)
but it still doesn't work - when I log off the SessionEnding event is never
fired, but I get a window ".NET-Broadcast Event Window 1.0.5 - This program
is not responding" etc. I would guess that this is because I am not calling
Application.Run because I need to run my own loop waiting for my named event.
Any further suggestions gratefully received. (Maybe I need to make it a
Windows application and override WndProc?)


I've tested this application and it works for me:

---8<---
using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;

class App
{
static void Main()
{
EventWaitHandle closing = new ManualResetEvent(false);
bool running = true;

SystemEvents.SessionEnded += delegate
{
running = false;
closing.Set();
File.WriteAllText("\\Log.txt", "Session ended");
};

Thread worker = new Thread((ThreadStart)delegate
{
for (;;)
{
WaitHandle.WaitAny(new WaitHandle[] { closing
/* , X, etc. */ });
if (!running)
break;

// Do work because of event X or whatever
}
File.WriteAllText("\\Closed.txt", "Success!");
});
worker.Start();

Application.Run();
}
}
--->8---

Perhaps you can adapt your application along these lines?

-- Barry

--
http://barrkel.blogspot.com/

May 30 '06 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: John Lull | last post by:
I'm writing a multithreaded COM server to manage a pool of hardware resources. All objects are designed to be thread-safe, and I've set sys.coinit_flags to COINIT_MULTITHREADED before importing...
8
by: Ben | last post by:
Hi all, I implemented a stack in C++ in 2 different ways and I'd like to know which approach is better than the other.. and if there is any difference between the two? I'd also like to know if...
70
by: Rajan | last post by:
Hi, I am trying to simulate a memcpy like this void* mem_cpy(void* dest, void* src, int bytes) { dest = malloc(bytes); } Now if I want to copy the bytes from src to dest, how do I copy these...
7
by: Jeroen Ceuppens | last post by:
Hi, When I draw a bitmap on a form, the bitmapdrawing disappears when I move the form, how is it possible to lock the drawing so it stays visible when you move or do somethings else.... Thx...
10
by: Charles Law | last post by:
For some reason, when I click the X to close my MDI parent form, the action appears to be re-directed to one of the MDI child forms, and the parent remains open. I am then unable to close the...
1
by: kevininstructor | last post by:
I created two classes called "site" and "Sites" which use 'BinaryFormatter' to load and save class information to a disk file. In my test application all works fine but when implementing into...
2
by: ern | last post by:
My command-line application must be able to run text scripts (macros). The scripts have commands, comments, and flags. Comments are ignored (maybe they are any line beginning with " ; ") Commands...
6
by: Dasn | last post by:
Hi, there. 'lines' is a large list of strings each of which is seperated by '\t' I wanna split each string into a list. For speed, using map() instead of 'for' loop. 'map(str.split, lines)'...
7
by: koonda | last post by:
Hi all, I posted my message earliar and I got some positive feedbacks but that didn't help me to solve some programming problems. I have an Assignment due 20th of this month, next monday. The...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.