I've created a managing application. On of the things my application does, is register on a plugin which can detect whenever or not a fingerprint reader gets plugged in or plugged out. The class subscribes on the event like such:
//Subscribe to the plug, unplug and imageAcquired events from the GrFingerXCtrlClass library.
FingerXCtrlClass.SensorPlug += ReaderPlug;
FingerXCtrlClass.SensorUnplug += ReaderUnplug;
FingerXCtrlClass.ImageAcquired += ImageAcquired;
First when I was actively working on the program, I've developed a WPF application. Through this application I could see some of the lists and switch some settings so I am sure my service works well. In this WPF application, I've created my service by instantiating it:
ProjectServiceLogic logic = new ProjectServiceLogic();
Now I've created an installer. Thus I had a ProjectService-class, initializing the application. This is being done like so:
protected override void OnStart(string[] args)
{
log.Debug("Starting service...");
_worker = new Thread(new ThreadStart(StartService));
_worker.IsBackground = true;
_worker.Name = "ServiceThread";
_worker.SetApartmentState(ApartmentState.STA);
_worker.Start();
log.Debug("Successfully started service");
}
void StartService()
{
serviceLogic = new ProjectServiceLogic();
while (!_shutdownEvent.WaitOne(0))
{
}
}
The program gets installed and the service starts. When debugging the service, I notice the subscribing code gets executed. However, the events are not triggered when I plug in a device while it does trigger when running it locally through the WPF application, instantiating the service logic. Why doesn't it work now?
_worker.SetApartmentState(ApartmentState.STA);
Selecting a Single Threaded Apartment requires you to implement the contract of an STA thread. Just two basic requirements: you can never block the thread and you must pump a message loop. The message loop is essential to allow COM to provide the guarantee that method calls on the COM object are always made from the thread that created the object, thus ensuring thread-safety. Also the mechanism in .NET that makes Control.BeginInvoke and Dispatcher.BeginInvoke work.
A COM component counts on having that guarantee in place, it often relies on the message dispatcher to take care of its own inter-thread marshaling. Like Dispatcher.BeginInvoke does.
Two things go wrong when you don't in fact pump a message loop as required. First of all, as expected, any calls you make on the object from a worker thread will deadlock. COM will use PostMessage to ask the STA thread to dispatch the call. But that won't happen when the thread isn't retrieving messages from the message queue. Second thing that goes wrong is likely what you see happening here, the component itself uses PostMessage to raise events on the STA thread. With the failure mode that the event is never raised. Also classically the way WebBrowser misbehaves, you never get the DocumentCompleted event.
You'll need to pump a message loop, Application.Run(). Either the Winforms or the WPF version of it will do, take your pick. A Winforms example is here
Related
I have created a Windows Form application for smart device in c# which will raise an
event whenever there is a change in registry data. I have used RegistryState and the following code from msdn site. I am able to successfully raise the event.
RegistryState state;
private void Form1_Load(object sender, EventArgs e)
{
// SystemState state; // This instance will go out of scope if defined here
RegistryState state = new RegistryState("HKEY_LOCAL_MACHINE\\MyKey", "MyValue");
state.Changed += new ChangeEventHandler(state_Changed);
}
But when I use the same code and create a console application, event is not getting triggered.
What could be the reason? Does RegistryState have any limitations?
You'd have to use Reflector to dig into it, but my strong suspicion is that down in its depths the ReegistryState class works a lot like the SHChangeNotifyRegister API. It uses Windows Messaging to signal state changes, so it must have a message pump that's watching for and dispatching those messages and some place to send them when they come in. A console app doesn't have a message pump, and therefore while the message is likely getting queued that the registry has changed, there's nothing pulling that message off and forwarding it to your RegistryState handler.
It would be easy enough to test (and work around). Just add a message pump to your app that does a the usual GetMessage/TranslateMessage/DispatchMessage periodically.
I'm writing a Windows Service in .NET 3.5.
The typical programming model for a windows service is to override the OnStart method to assemble your classes before initiating any long-running processes on another thread.
This is because the OnStart event must return after a default of 30 seconds before a timeout.
In my scenario this thread is vitally important and so I want to create some form of heartbeat system to monitor its state and recycle / recreate it if necessary.
Ideally I would perform this heartbeat check from the main application thread (because the heartbeat must never die) but I do not see how I can marshal any new calls onto that thread.
How would you solve this problem?
Perhaps my intended approach is wrong? If so, how else would you approach it?
Here's what I have. When my application starts up, it creates a thread and runs my startListening() function. But what it seems to do, is run any other functions called within startListening under the same thread. Is there a way I can make it so that ONLY the things immediately inside of startListening are ran with that thread, and not the functions called from within that?
It would just make it a lot easier for me when referencing controls and things that aren't within that thread so I don't have to Invoke each time.
EDIT: Maybe this isn't the right thing to be asking. I know I had to Invoke with setting textboxes, but now I need to make a timer enabled. Its not throwing any exceptions when I try to enable it, but rather just not "ticking". Here's my code:
private void beginListenerThread()
{
Thread thread1 = new Thread(startListening);
thread1.Start();
}
private void startListening()
{
timer1.enabled = true;
}
But it doesn't tick.
Thanks!
No, that's not possible automatically. If you are able to modify the method that should be called on another thread, change the calls to other methods so that they're run on the originating thread. If you're using Windows Forms, use this.Invoke or this.BeginInvoke, for example.
Yes, this is the kind of trouble you'll run into when you use a class that is not thread-safe on a thread. The Winforms Timer class generates Tick events from a little hidden helper window, a window that receives WM_TIMER messages generated by the Windows SetTimer() api function and turns them into Tick event calls. That window is created when you enable the timer.
What goes wrong here is that this window gets created on the wrong thread. It needs a message pump to dispatch the WM_TIMER notifications, that thread doesn't have one. It could have one by calling Application.Run() but you don't want to go there.
Follow the advice given in the MSDN Library article's Remarks section:
The Windows Forms Timer component is single-threaded, and is limited to an accuracy of 55 milliseconds. If you require a multithreaded timer with greater accuracy, use the Timer class in the System.Timers namespace.
Or the System.Threading.Timer class, a timer class that's a bit less cranky.
All
I have an application that allows a user to communicate with multiple serial devices.
A manager class is used to start the application, which creates a new thread for each serial device. Inside this thread, the serial device is created and the thread and serial device object are stored inside the manager class for later when needed.
The serial device class then creates a com port class on it's own new thread which is used to connect to the com port and send / receive data. When data is received an event is fired up to the serial device class which in turn fires an event to the manager class, which in turn fires an event to the UI to alert the user that new data has arrived.
My problem comes that when the com port class fires it's event to notify the serial port class, the serial port class receives the event and continues processing under the com port thread. Likewise if the user sends any information down to the com port, it all runs under the UI thread.
I will add code as an edit later, but for now, if anyone can spot anything obvious I would be seriously greatful.
I have tried receiving the event in the serial device class and then invoking a method to see if that makes it run under the correct thread but that was no good.
I know the serial device thread is running as I do an Application.Run inside the class after it's created it's com port classes.
I'm not using any background workers as these threads are meant to exist for the life of the application and I understand background workers are meant to be used for short running calculations.
Many thanks
EDIT:
Forgot to mention, this is a Winforms app in .NET 2.0, so no Dispatcher available
EDIT:
Okay, so it looks like that the information is being passed up inside the DataReceived thread (I think as it isn't the com port thread either).
I also tried using a BackgroundWorker for the serial device class but this also didn't make any difference.
Help?
.NET 2.0 has SynchronizationContext. It's a slight pain (you have to pass the context from the UI thread to the others) but it should do the trick.
More info here: http://msdn.microsoft.com/en-us/magazine/gg598924.aspx
It sounds as if you need to create a kind of messaging mechanism to send messages from the UI thread to the correct port-thread. A queue might work. Let the UI thread post messages on the queue and have the port-thread process these messages.
Switching from the port-thread to the UI thread can be done using Dispatcher.CurrentDispatcher
Is this what you are looking for?
EDIT I am assuming a WinForms application
I am developing an application that is split into multiple .NET assemblies (one main executable and a set of class libraries). Currently, I am using a WPF GUI, but I need to maintain the flexibility to possibly switch to another GUI framework at a later time.
Here is my problem: one of the class libraries performs some work on a separate thread, and raises an event when that thread is complete. I quickly discovered that my WPF GUI got upset when I tried to modify its components from this event handler, so I implemented an "event queue" that dispatches events on the main thread using a System.Windows.Threading.DispatcherTimer. This did the job; however, I was horrified to discover that this DispatcherTimer only works within the context of a WPF application!
I am trying to hide all the ugly details of multithreading within this class library, which may eventually be used in conjunction with a non-WPF GUI. The idea is, the consuming application should be able to update its GUI from within the event handlers. So, my question is, is there a standard method (independent of any particular GUI framework) for raising events on a different thread??
Any help would be appreciated. Thanks.
You need to use ISyncronizeInvoke. This interface allows you to check if you are on the right thread, and if not, Invoke a method on the correct thread. I haven't done this in WPF, but I assume it is implemented there as well as Windows Forms.
Typically you would just marshal the event data to the main thread by reinvoking the event handler from the main thread. One method is shown below.
private void DispalyMessage(byte[] bytes)
{
if (this.InvokeRequired)
{
lock (_lock)
{
EventHandler d = new EventHandler(DispalyMessage);
this.Invoke(d, new object[] { bytes });
return;
}
}
else
{
//do something with the data
}
}
Enjoy!
You could use SynchronizationContext (which is what BackgroundWorker does, I believe) - or you could just warn your clients that the events will be raised on a background thread, and that they should perform whatever marshalling they need to (as other APIs like FileSystemWatcher do.)
Instead of events from the class library, use a callback method that your GUI code provides. Although the callback will be invoked on the library's thread, your GUI code can decide what's the best way to handle it. This should simplify switching to a different GUI.