I've a pretty simple question/issue. I want to use 0MQ for some pretty basic Pub/sub functionality. My subscriber app is a windows GUI based app using plain winforms.
As there seems to be no explicit reference in 0MQ for handling this scenario, I am assuming that worst case I'd have to use a BeginInvoke(...) on the windows GUI thread once the 0MQ thread has recieved any subscription message. This seems pretty straightforward but if anyone has any insight/opinion/heads up in terms of the best way to handle this I'd very much appreciate it.
Thanks in advance
David
For your ZeroMQ subscriber in a WinForms application you have at least a few options:
Use a background worker thread to receive your 0MQ message. When you receive a message pass it to your background worker progressChanged event to update your UI.
Use a system thread to receive the message and invoke to update your UI.
Another suggestion on SO also suggest using a system thread to queue the message upon receive and a timer event to dequeue the message. If you used a Forms Timer you could update the UI without invoking or if System Timer you would need an invoke.
Which method you choose depends on your design criteria.
As pointed out, there are several ways to hook up ZeroMq into a WinForms app. It really does not differ much from using ZeroMq and C# in other settings, like in a console application. The main difference is as you point out that you have to get the messages into the Gui thread in order to update your Gui controls.
An example of using a separate thread + queues (producer/consumer pattern) can be found here: Examples of zeromq pub/sub with C# winform
Another way could be to use (again) a separate thread to do the ZeroMq work and set up an event that gets fired each time a message is received. The Gui could then hook up an event handler and process the message. You would of course also have to invoke any updates to the Gui. A drawback to this approach is that the event processing will interfere with the ZeroMq handler thread a bit, especially if the Gui updates takes a while, and if you receive lots of data.
All solutions have their pros and cons, it all depends on how your particular problem domain looks. All-in-all, integrating ZeroMq into a C# application, be it WinForms or other, is IMO pretty straightforward. The clrzmq wrapper is well-written and easy to use. The problems you may run into has more to do with the limited error feedback in ZeroMq itself. If you encounter strange crashes; try to run the same logic in a console application, that will give you better error messages.
Related
I have some commercial equipment that I can connect to with a .Net library supplied by the equipment manufacturer - so I have no control over the library or the equipment, only my code.
The manufacturer has set their system up so that if you are not connected to the equipment via their library then it works fine. However, when you do connect with their library there is an implicit requirement that you service Windows message pump at a rate set by how fast the equipment is running. This is because their library implements an event system that you can subscribe to that tracks operation of the equipment, but they assume that your application code will be WinForms based. (But there is nothing explicitly stating this in their documentation - only that all 2 of their .Net example programs are WinForms based.) I have confirmed with their tech support that the expectation is that you will use a WinForms application.
In my case I am writing a C#, non-WinForms based application (actually a Windows Service, so I do not have a UI thread) and even though I am connecting to the equipment I am not subscribing to any of the events. As a result I have found that I need reference the WinForms assembly and call Application.DoEvents() at a fast enough rate to service all of those events that I do not subscribe to.
So my questions are these:
In this case is calling Application.DoEvents() my only option?
Or is there a more modern way of doing this?
What are the ramifications of calling DoEvents() on a 20mS rate?
Unrelated, but if I wrote a WPF based application would that program be likely to service the message pump?
Edit
I should add that if you connect to the equipment and do not service the windows message pump (even if not subscribed to any of their events), then the equipment falls starts to behave unpredictably.
Edit 2
Also the thread I use to interface to the library is about 2 or 3 generations removed from the initial windows service thread.
This is fine, the usual caveats for DoEvents do not apply here because you don't have a UI. There are no ramifications, the rate is realistic. Application.Run() also pumps the message loop but you'll have a harder time controlling the thread since the call doesn't return. Yes, WPF pumps the message loop too but there's little point in using it since you don't have a UI.
You should initialize the service thread by calling SetApartmentState() to select STA. This ensures that any COM server works properly.
Oh, one caveat that jumps to mind: you do need to do something to prevent the thread from burning 100% core. It is automatic with Application.Run() but not with DoEvents in a 'game loop'. I think you already do since you can specify a 20 msec rate. Otherwise, calling WaitHandle.WaitOne(20) on the service stop request event is the typical approach.
You can have a message pump without forms just call the version of Application.Run() that takes a ApplicationContext or no parameters on a thread.
EDIT: I would recommend the ApplicaitonContext version so you can call ApplicationContext.ExitThread() in the OnStop() of your service.
Problem description: you write a library which contains some algorithms/tasks which can take a long time to finish, for various reasons: computational, file system, network communication etc. You want to be able to:
Send some progress information about the task (progress, activity logging etc.)
Have a way to abort the task before completion if some external signal or property has been set.
I've implemented a framework for this, but this requires that all such tasks have to reference an assembly which contains this framework.
My question: is there an already built-in mechanism in .NET framework (3.5 or below) for the problem described above?
I know I could use events, but this would mean long running tasks would have to expose such events, which I think is an overhead. Ideally I want to have a framework which hides away multithreading issues and is dependency-injection friendly, but would not depend on an additional custom assembly and would not pollute the original interface.
I hope I described the problem well enough. If not, I can post some samples of the interfaces from my own framework.
UPDATE: OK, I think my problem description needs a bit of clarification :). When I say "long-running", I don't mean "long" in the workflow-sense. I'm working on a WinForms mapping app which does all sorts of stuff, like generating relief contours. To do this, it first has to download the elevation data files from a FTP server, unzip them and then perform some calculations. I wrote the code for this a long time ago, but in order to make it more GUI-friendly, I have to retro-fit various checks - for example, detecting that the user has clicked on the Abort button and stop the process.
So basically my concern is: how to write a code that can later (if ever) be used in a GUI environment, where you cannot simply run everything in the main GUI thread and freeze the whole application. The challenge is to find a way to make your code suitable for GUI purposes without tying it to a particular GUI platform.
That sounds a lot like Windows Workflow Foundation.
Take a look at the saga pattern. It's not built into the framework but can be implemented. Alternatively both NServiceBus and MassTransit have implementations of this. Arnon RGO has a draft from his book (will it ever be finished) describing it here.
In my experience getting going with NServiceBus is much simpler than WF, and is also more powerful (though I haven't looked at WF 4, which by all descriptions is a near complete rework of WF as Microsoft have recognised the failings of this).
Even if you don't want a framework like NServiceBus or MassTransit, the pattern itself, is well worth looking at as it fits your problem space very closelyfrom what you have described.
It depends on how complicated your system is. For relatively simple problems, you could probably nicely use the BackgroundWorker class from .NET 2.0. It supports reporting the progress of the operation using OnProgressChanged event and it also supports cancelation of the background task using CancelAsync method.
The class is controlled by events, but since that's already a part of the class, I don't think it is any overhead for you:
var bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted);
bw.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
The DoWork method is executed to run the background task (it can report progress by calling bw.ReportProgress and check for pending cancellation using bw.CancellationPending).
The RunWorkerCompleted method is executed on the GUI thread when the operation completes (which gives you a nice way to synchronize without worrying about concurrency)
The ProgressChanged event is triggered whenever your DoWork method reports some progress change.
For simpler problems, I believe you could represent your tasks as background workers.
I prefer to use callback methods to signal the UI thread when something's done or progress needs to be updated. You can pass complex objects and the callback can return a value in case it needs to signal the worker thread. And you're allowed to have multiple callbacks defined depending upon how chatty you need your workers to be.
I was writing up a long, detailed question, but just scrapped it in favor of a simpler question that I didn't find an answer to here.
Brief app description:
I have a WPF app that spawns several threads, and each thread executes its own WF. What are some of the best ways to handle errors in the threads and WF that will allow user interaction from the GUI side? I definitely plan to handle any low level exceptions in the thread, because I don't want the thread to exit.
Summary of questions:
How have you implemented communication between WF and the thread that starts it? There is WorkflowTerminated, but I don't want the workflow to exit -- I need to fix the problem and let it continue. I assume the only option is using a FaultHandler, but was wondering if there's another way to do it without using an activity block. I am hoping there's a framework out there that I just haven't found yet.
The error from WF needs to get caught by the thread, which then needs to display the error in the GUI. The user will then make a logical choice for recovery, which should then be sent back to the thread, and then to WF. Again, is there something existing out there that I should take a look at?
Even buzzwords / keywords that accomplish what I am describing would be really helpful, and I can do the legwork on researching each of them. However, any additional insight is always welcome. :)
What's worked for me in multi-threaded WPF apps is to have the errant thread invoke a callback method that passes the exception and other info back to the UI thread. Callbacks can have return values, so if your thread can block while waiting for the user to respond, then that can work for you. Remember that the callback will run on the thread that calls it, so any UI updates have to be done via the control's dispatcher. You will have to decide whether all of the threads use the same callback and what kind of synchronization you'll need if there's a chance that multiple threads can throw exceptions simultaneously.
Here's how I ended up solving this problem. But first a little background info:
User clicks a button in the GUI that causes the candy packager to start running. This is done via a command binding in the ViewModel, which then calls a low-level function in the Model. The function in the model launches a thread and executes a state machine.
At some point, the machine will fail. When it does, I compile information about the error and possible (known) recovery methods. I put this into an object and then pass it to the GUI via a callback interface. In the meantime, the worker thread is stuck waiting for an Event to get set.
Eventually, the candy worker will notice the error and will click a button telling the system what to do. This results in two things: 1) it flags one of the recovery methods as the preferred one, and 2) sets the event. Now the worker thread continues on, checks for the preferred error recovery method and transitions into the respective state in the state machine.
This works very well (so far). The part I know is totally lame is the manner in which it checks for the preferred error recovery method. I am essentially setting a string variable, and then comparing this string to a list of known strings. Ultra lame, but I'm not sure of a better way to do this, other than using an enum. Does anyone have recommendations for me?
We have an application with multiple subsystems running in different threads (ie one thread monitors the GPS, another monitors a RFID reader etc). The threads are started and monitored by a service registry which is seperate from the win forms part.
The initial release of the App just had a single form which would run on an update timer and just check the values of static variables on each of the subsystems every second or so.
I'm trying to clean this up, as we're adding in extra forms and there's virtually no thread safety with the current approach. I want each subsystem to throw a new event when its underlying state has changed so each form can subscribe only to the events it cares about and we can move to a more responsive UI...I don't like the update timer approach.
I'm running into problems here as events are triggered in the subsystems thread so I get System.InvalidOperationException exceptions complaining about cross thread calls when I try and update the UI with any state that is passed through with the event.
So at the moment, after reading through the msdn documentation, my options are to use control.invoke for each field I wish to update which is pretty annoying on complex forms with lots of fields, use background workers to run the subsystems in the forms themselves or have the forms still run on a timer and query the subsystems themselves, which I'm trying to avoid. I want the forms to be as separate from the underlying system as possible...they should only know which events they care about and update the relevant fields.
My question is, what am I missing here?? is there a better way I can architect this system so that the subsystems can run in their own threads but still send notifications off in a non coupled way?
any help would be greatly appreciated
cheers
nimai
Rather than invoke across for each field you want to update, use a MethodInvoker delegate with BeginInvoke and call a method that does all your updates at once. For example ...
BeginInvoke( new MethodInvoker( MyUIUpdaterMethodHere ) );
You can take a look at Event Aggregator pattern which basically allows a loosely coupled pub/sub type event-based architecture. Prism, a framework from Microsoft Patterns and Practices team for building composite applications with WPF and Silverlight has event aggregation that allows different UI components to communicate with each other in a loosely coupled way similar to your design goal. You can take a look at it and try to use just the event aggregation part of it. If not, you have access to the source code so that you can craft something that fits your requirements.
You could use Windows Forms Synchronization Context to pass in a SendOrPostCallBackDelegate(or a lambda) which in turn can update multiple controls in a thread safe manner.
It sounds like these subsystems are running as a windows service.
How is your winform app communicating to these sub systems.
Events are synchronous in C#. I have this application where my main form starts a thread with a loop in it that listens to a stream. When something comes along on the stream an event is fired from the loop to the main form.
If the main form is slow or shows a messagebox or something the loop will be suspended. What is the best way around this? By using a callback and invoke on the main form?
Since you're using a form, the easier way is to use the BackgroundWorker component.
The BackgroundWorker class allows you
to run an operation on a separate,
dedicated thread. Time-consuming
operations like downloads and database
transactions can cause your user
interface (UI) to seem as though it
has stopped responding while they are
running. When you want a responsive UI
and you are faced with long delays
associated with such operations, the
BackgroundWorker class provides a
convenient solution.
Hmmm, I've used different scenarios that depended on what I needed at the time.
I believe the BeginInvoke would probably be the easiest to code since you're almost there. Either way you should be using Invoke already, so just changing to BeginInvoke. Using a callback on a separate thread will accomplish the same thing (as long as you use the threadpool to queue up the callback) as using BeginInvoke.
Events are just delegates, so use BeginInvoke. (see Making Asynchronous Method Calls in the .NET Environment)
You have a few options, as already detailed, but in my experience, you're better off leaving delegates and BeginInvoke, and using BackgroundWorker instead (v2.0+), as it is easier to use and also allows you to interact with the main form on the thread's completion. All in all a very weel implemented solution, I have found.
System.ComponentModel.BackgroundWorker is indeed a good starting point. It will do your asynchronous work, give you notifications of important events, and has ways to better integrate with your forms.
For example, you can activate progress notifications by registering a handler for the ProgressChanged event. (which is highly recommended if you have a long, asynchronous process and you don't want your user to think the application froze)