Well, you've found two annoying things:
1) a misleading bit in the help text, and
2) an overzealously helpful default in new console applications.
COM interop for console apps pretty much requires the STAThread, especially
if you are using APIs like MAPI that actually do the *wrong* thing in a
multi-threaded environment. That said, I suppose there are other reasons
that someone would want to force the app to be apartment threaded (although
COM compatibility is surely the most common). The attribute doesn't say
[COMCompatible] or some such nonsense. It says [STAThread]. Not the same
meaning. Therefore, the comment in the help text is anything but helpful.
It doesn't really have anything to do with console apps, per se.
I'm glad you found and fixed your problem.
--- Nick
Joe said:
Nick,
Thanks again. Removing the [STAThread] attribute solves the problem, but
I'd still like to understand why. I'd have thought [STAThread] would be
irrelevant for a console application main thread (not sure why VS.NET adds
it automatically). Also the documentation for STAThreadAttribute states
that "Using this attribute in an application that does not use COM interop
has no effect."
I disassembled SystemEvents.EnsureSystemEvents and it includes code like the following:
if (!SystemEvents.UserInteractive || (Thread.CurrentThread.ApartmentState == ApartmentState.STA))
{
... initialise ...
}
else
{
... create a background thread and initialise ...
}
So I can see what is happening, but not why.
Nick Malik said:
Hi Joe,
Yes, but your program has the [STAThread] attribute. That means "Single
Threaded Apartment Threading model". In other words, you are planning to
call COM components, and you need to be certain that you will only run on
one thread.
If you want MTA Threading, just drop the attribute.
--- Nick
Nick,
Thanks for responding. The framework documentation states "When a system
event is raised calls back the corresponding delegate from a different
thread. "
I assumed (and disassembly of the SystemEvents class seems to confirm)
that it would create a thread with a hidden window to listen for a
WM_TIMECHANGED message.
Joe
:
Hi Joe,
Your app is single threaded. What thread is it supposed to execute the
event handler on, if you are waiting for input from the console?
--- Nick
Can anyone tell me why the code below doesn't work? Run the console
app
and change the system date/time: why is the TimeChanged event handler
not
executed?
It works fine in a WinForms application, but I can find nothing in the
documentation to suggest that the SystemEvents class can only be used in
a
WinForms app (if this were true, surely it would be in the Windows.Forms
namespace).
Thanks,
Joe
using System;
namespace ConsoleApplication1
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
Class1 class1 = new Class1();
Console.Write("Change the system time or Press ENTER to
exit");
Console.ReadLine();
}
public Class1()
{
Microsoft.Win32.SystemEvents.TimeChanged +=new
EventHandler(SystemEvents_TimeChanged);
}
private void SystemEvents_TimeChanged(object sender, EventArgs
e)
{
Console.WriteLine("Time changed");
}
}
}