Reputation: 9087
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.
Upvotes: 3
Views: 1388
Reputation: 62127
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:
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.
Upvotes: 1
Reputation: 4084
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.
Upvotes: 0
Reputation: 6901
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.
Upvotes: 3