Do you have any ideas how to call DoEvents from a C# DLL
Don't. It's sketchy enough when you are the app controlling the event loop; pumping messages from a DLL just adds to the risk that you'll end up hitting code a naive programmer didn't make safe for re-entrancy.
Do you mean System.Windows.Forms.Application.DoEvents()?
I'd echo the "don't" (either from a dll or a UI project). There are several things you can do to make library code play nicely with a UI,including the same threading tricks (with events and/or callbacks) that you might use from the UI. The simplest approach is for the library code to simply execute "as is", and if the UI happens to spawn it on a worker thread, then it is the UI's job to handle any events and marshal them (Control.Invoke/BeginInvoke) to the UI thread for UI updates.
For more complex scenarios, you can use the sync-context (SynchronizationContext.Current) to post messages to the UI thread (this is actually how Control.Invoke etc work, but it is implementation independent - so a WPF sync-context can go through the WPF dispatcher).
Can you add more context on what the scenario is? There are many things that can be done...
Write a interface for the EXE and have your main form or main class implement it.
Then register that object implementing the interface with the DLL.
Assign it to a variable of the that interface type
Make a Subroutine that is visible throughout the DLL.
In the Subroutine check to see if the variable is nothing if isn't then the subroutine that fires method you created to fire DoEvents.
Anytime you need to do a DoEvents then call the Subroutine.
If you are using a three tier organization for your application put the subroutine or variable on the object representing your entire application. Have the form register itself with the Application object.
If you have re-entrancy problems you can add status variable and other helper functions to safely check what the application is doing. Note that is far far easier to implements this if you are using some type of multi-tier design.
To other looking at this re-entrancy is a problem however so is a non-responsive UI. In a complex application there are circumstances where you have to let the event loop fire.
Related
I am pretty sure Applicataion.DoEvents() in Windows Forms. is a very early, very primitive, WindowsForms only form of Multitasking. It has all the telltales and mechanics:
Pausing execution of the calling Event.
Making the rest of said Event a continuation to be run later.
Allowing the other Events/Processes to run. Just with some extra issues, because the MT is implemented via the EventQueue. Possibly even a recursive call to the Queue.
But I just ran into a person that insists it has "nothing to do with Multitasking", which I cannot reconcile with my understanding of the Function or the of Multitasking.
Note: I explicitly consider Mutltithreading only an implementation for Multitasking. It is clear that DoEvents() is not a form of Multithreading, as we all know how poorly that one works in GUI Environments.
I am pretty sure it is a very early, very primitive, Windows Forms only form of Multitasking
You are pretty close to correct on all counts except for your conjecture that it is for WinForms only. "DoEvents" precedes WinForms; it was present in Visual Basic long before WinForms was invented, and "pump the message queue" obviously precedes VB also. And it was a bad idea and easily abused then too.
Making the rest of said Event a continuation to be run later.
DoEvents doesn't really make anything into a continuation the way that say, await does. Whatever event is currently "in flight" when DoEvents is called has its state on the stack, and the stack is the implementation of continuation in this case. This is another point against DoEvents -- unlike await, it eats stack, and therefore can contribute to an overflow.
I just ran into a poster that insists it has "nothing to do with Multitasking".
You should ask the author for clarification then, since that certainly sounds wrong.
Well, it's called Preemptive Multitasking, meaning "interrupting a task". You do multiple Tasks, but never two at the same time. It's not about using multiple cores of the CPU, but a way to control multiple activities inside your program.
Common Sample is, to give the program a chance to handle mouse movement by the user, while doing a lengthy operation, running something that can be considered a "batch"-job.
Normally you don't have to care about this "DoEvents", but if you know, you have a procedure running for more than 1 second, you should call it manually, you pass the control to another method thereby, you stop your own code, let other code run, and than you continue with your own code.
So it's never asynchronous, but still some kind of "multitasking".
It's more a control structure, the important thing is, you do not know what's going on inside, you call it "just for case" - somebody else might need the CPU for a millisecond.
There is no external task scheduler interrupting your code and doing a context switch, you have to "behave" by interrupting your code yourself, if you do something lengthy. It is a convention that you do only "small" things in event handlers and return the control to Windows as soon as possible,either by finishing the method, or by calling DoEvents.
We've implemented our main code functionality in a C++ Dll then written a C# UI on top. This works fine most of the time, but in areas where we want the UI to report the progress of a function in C++ we're having some performance problems.
We pass a pointer to a C# function down to the Dll to use for progress updates. When it's called we use InvokeRequired and Invoke() to make sure the callback is thread-safe. Measured from the C++ side, this can take anything between 16ms and 180ms. Is there any way of reducing the time this takes?
One of these callbacks passes the location of a line to be drawn on the screen. This drawing currently very slow - I assume the invoked functions are queuing up and taking time to be drawn in C#. I can see two ways of dealing with this:
1. Change the callback to send a list of lines and allow the lines to queue up in C++ whilst waiting for the previous call to C# to complete.
2. Adding the lines to a queue in C# (preferably without calling Invoke) then drawing all lines that are available at once.
Any suggestions on how to do this, whether both options are required, or alternative methods?
Thanks for any and all help.
You can use BeginInvoke instead of Invoke. Invoke waits for the function to return, while BeginInvoke allows the function to run parallel to the current thread.
Your problem is not the callback but likelys the invoke. Invoke is a potentially expensive operation. If you ahve a thread change there, it WILL take time. A lot. You alsoa re putting the drawing operations into the same thread, so the callback will block until those are finished.
What you can do:
BeginInvoke - basically the callback erturns early, another thread does the drawing.
Reduce the number of invokes, basically batching your requests. This can be done OUTSIDE The C++ dll - have the callback put the corodinates into a queue, then the queue in a separate thread call BeginInvoke.
Basically, your single threaded UI and the requirement of thread switching via dispatcher kill you, totally within the C# area.
At the end, your question is badly worded. C++ & C# has nothing to do with the problem, you would have the same issue with C# only. You have an API making callbacks into the UI that needs to switch threads (Invoke) and do UI operations, and this leads yo t he callback taking more time than you want. Replace C## with Smalltalk, Assembler, C#, Visual basic and the problem stays 100% the same.
As far as I understand your question, there is only one line, which should be drawn. But its coordinates are frequently generated in the unmanaged part and sent to C# to update the graphical representation? Consider enabling the drawing method to cancel itself. So when - while drawing a line - new coordinates arrive, discard the current line and just draw the new coordinates. That way you may get rid of the need to implement any queueing at all.
#Edit: I tend to the suggestion to better query all necessary data from the C++ part by C#. It sounds like you are calling back to .NET very often in order to control some visual output. But this should be done from .NET (which knows much better, how often it is possible at all). So, querying all data from C++ in a user defined structure may help.
I've got a bit of an issue here where I want to modify GUI elements from various worker threads. Until today, the method I was using worked, but it was most likely very incorrect.
The simplest case involves my plugin's GUI, which does something in a worker thread, and when that method completes its work, it calls my callback. That callback method is handled from the same thread, so it cannot do any GUI work. However, when my plugin's GUI is displayed by my main app GUI, my plugin GUI caches its Dispatcher reference -- when I do need to do GUI updates (or in this case, display a dialog), I call Dispatcher.Invoke(...).
Is there any inherent danger in setting the Dispatcher in my plugins like this?
Today, I have a new problem with this approach. My application needs to call that method in my plugin that launches the worker thread and displays a dialog. If I call the method before I open the plugin's GUI (which caches the Dispatcher reference), the operation will fail because the Dispatcher is null. I always check for that to make sure the app doesn't crash. However, now that the dialog isn't displayed, the necessary user interactions cannot proceed.
Can anyone suggest a better method for using the Dispatcher to ensure that I can display / modify a plugin's GUI elements from my main application? The only thing I can think of right now is to have my main application pass its Dispatcher reference to my plugin loader, add a "SetDispatcher" method to my plugin interface, and then have the plugin loader call this for every plugin that needs to be loaded.
If your plugin's GUI must exist by the time the background thread finishes, you should probably make sure that the plugin GUI creation/instantiation happens before you spin off that background process. That way, the plugin GUI element(s) Dispatcher is set by the framework before your async stuff finishes.
At a higher level (you may or may not be able to address this), it seems like you've got some inappropriate coupling between the GUI and the stuff that's occurring in the background.
For now, I've found that a nice solution, appropriate or not, is to export the main thread's Dispatcher via MEF, and then allow all of the plugins to import it. It seems like the cleanest way to deal with this sort of thing right now.
I'm writting a Windows Forms application in C# that performs a lot of long-running procedures. I need to program the application so that the GUI doesn't lock. What is the best way to program it?
I know how to use the following:
BeginInvoke/EndInvoke
Calling Application.DoEvents() repeatedly (probably not a good idea)
BackgroundWorker
etc.
But how to manage GUI state with call backs, etc... is not trivial. Are there solutions for this (in the form of patterns or libraries)?
Using BackgroundWorker is the simplest way to do what you're trying to do. BackgroundWorker simplifies the logic of dealing with threads, leaving you with very little code you have to write. You just have to handle three events (DoWork, ProgressChanged, and RunWorkerCompleted) and follow a few principles:
Don't ever update the UI inside your long-running method. Have it call ReportProgress instead and handle the ProgressChanged event in the UI logic.
Understand that since the worker isn't running on the UI thread, an exception that your method throws doesn't automatically show up in the UI. It just gets silently written to the console. It's very important to check the Error property of the RunWorkerCompletedEventArgs when the method is done and handle (or throw) the exception. If you don't do this, you won't know that your method failed.
If the method can be cancelled, make sure that it periodically checks the CancellationPending property to see if cancellation has been requested. If it has, once it's done handling the cancellation, set the Cancel property on the DoWorkEventArgs object. Be aware that it's possible for CancellationPending to be true and Cancel to be false; this happens, for instance, when the user requests cancellation and the method finishes before it has a chance to check CancellationPending.
Correspondingly, check Cancel in your RunWorkerCompleted event handler, so that your UI can provide the proper response to what happened while the worker was running.
The examples in the documentation all show the DoWork event handler calling a method of the form. This is almost certainly not what you want to do. Separating business logic from UI is a good idea in general; in background tasks it's essential. If your long-running method is a member of a class that doesn't know that the UI even exists, there's no danger that you'll inadvertently have it call a method that updates a status bar or something.
The Model-View-Controller pattern separates the state of your UI from the visual aspects of the UI. As long as your MVC implementation is thread aware, it should solve the state management issue for you.
This is how I handle multi-threaded UI implementations.
EDIT: Here's a good post on selecting an MVC implementation for WinForms projects.
It is relatively simple to use the ThreadPool to fire off long running processes from the UI. If you want feedback you can use some event handlers to fire on certain events from the long running process, then register for them and update the UI as needed.
MVC is good, but you still need to make sure your process is firing off on a thread other than the UI thread.
All your options are syntactic sugar of doing same thing (Asynchronous execution). May be with different levels of controls. I would go with BackgroundWorker, because your GUI (handled by the main thread) will always be responsive.
I'm creating a C# dll, which is going to be used by others developers in WinForms. For some reasons, I want to detect, if methods from this library, are called from Main (GUI) Thread and warn developer he has done such a thing (ie. in log file). Is there any reasonable way to detect calling method from main thread?
Remember I have no access to WinForm application.
An easy solution in this case is to declare a static control in the library assembly that is created on the Main UI thread. If you want to detect if the library is called from the main thread, then use the following
if (MyLibraryControl.InvokeRequired)
//do your thing here
The simplest option (if you have a form/control handy) is to check InvokeRequired.
In the absence if that, you could try using SynchronizationContext to simulate a Post or Send, checking what thread that happens on? Calling Send or Post will switch to the UI thread.