I have a C# program seems stuck at random time, and after a random while it recovered itself! When it stuck, I can see the memory growth, and when it recover, the memory usage just drops to normal. The CPU usage seems normal all the way and there is no files is written or read (as designed).
The program calls an external (3rd party) DLL function to communicate with hardware, and updates the UI from the DLL's callback which running on a different thread. I have checked the code and found nothing suspicious apart from the following code (redacted):
private void Func(StructType para) {
if (labelA.InvokeRequired) {
labelA.BeginInvoke(new MethodInvoker(() => Func(para)));
return;
}
if (labelB.InvokeRequired) {
labelB.BeginInvoke(new MethodInvoker(() => Func(para)));
return;
}
labelA.Text = para.A;
labelB.Text = para.B;
}
I wonder if this is a proper way of update the UI element from another thread? If not, how to revise it?
In fact, I invoke 6 labels and another form (optionally). It seems working fine for most time but occasionally stuck. I can't post all code here for obvious reason, but just trying to troubleshot from where I doubt most.
Thanks in advance for any suggestions!
You don't need to individually check each each control to determine if you need to invoke it - there is only one UI thread, thus, that check is only useful once. Keep in mind - modifying any UI component is almost certain to cascade into a whole bunch of other reads/writes to other UI components; as a result of that, you have to make the assumption that if you are touching any UI object, you have to assume you're touching all UI components.
With that in mind, I'd recommend you perform your invoke check once, and I recommend performing the check and invoke on the parent control of both labels.
Assuming this refers to the class that is the parent to both those labels, I would modify your code as follows:
private void Func(StructType para) {
if (this.InvokeRequired) {
// Elide the explicit delegate declaration; it's not necessary.
this.BeginInvoke( Func(para) );
// Elide the return statement - multiple returns are messy, and in this case, easily removed.
}
else {
labelA.Text = para.A;
labelB.Text = para.B;
}
}
Be aware that InvokeRequired returns false if the object is disposed, even if the calling thread is not the UI thread.
Related
We are building a .NET application using WinForms (3.5).
I have added a new feature recently, and started experiencing weird behavior when accessing certain controls. The problem was that some UI control access simply halted the execution (no exception was seen).
Under close examination (using WinDbg) I realized the controls were being updated from a ThreadPool thread, and a CrossThreadMessagingException was thrown.
My question is -- is there any good practice on how to circumvent such behavior?
It would be very cumbersome but also perhaps not possible to surround every code location that accesses UI controls with the Control.Invoke method.
How can i partition my code to "safe" code that shouldn't use Invoke, from one that should?
If the application is designed to be multithreaded, then cross-threading can occur and thus you need to check for it using InvokeRequired, and either have the method you are calling re-Invoke() itself on the UI thread, or throw an exception that will indicate code is being used improperly. Keep in mind that InvokeRequired will be false in certain circumstances (mainly when the window doesn't have a handle or is being/has been disposed); the best way to prevent these circumstances is to not start threads earlier in the window initialization process than the Load() event handler, and to handle the Closing() event by cancelling background threads created by the window and waiting for them to close.
If the application is not multithreaded (you are not setting up BackgroundWorkers, TPL operations, BeginInvoke()ing delegates or Start()ing threads), then it's not necessary. However, calls to InvokeRequired are pretty cheap (the logic behind it is basically a check that the WinAPI functions GetThreadId and GetWindowThreadProcessId return the same value), so if you anticipate the program being restructured to be multithreaded, the following patterns for called methods are simple enough to implement:
//no return value, no parameters; ShowWindow(), HideWindow(), etc
//Understand that many built-in control methods are not virtual and so you can't
//override them to do this; you must either hide them or ensure the caller is
//checking for cross-threading.
public void MyWindowMethod()
{
if(InvokeRequired)
this.Invoke(new Action(MyWindowMethod));
else
{
//main logic
}
}
//Input but no return; SetTitle("My Title")
public void MyWindowMethod2(string input)
{
if(InvokeRequired)
this.Invoke(new Action<string>(MyWindowMethod2), input);
else
{
//main logic
}
}
//inputs and outputs; custom methods, advanced graphics
public string MyWindowMethod3(string input)
{
if(InvokeRequired)
return (string)(this.Invoke(new Func<string, string>(MyWindowMethod3), input));
//No else required; the return makes it redundant
//main logic
}
I'm running heavvy background work with Parallel.Invoke, after all processing has completed I return the method, return again, call a next method to utilize the calculated data I get the error:
Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.
But I already returned from the threads that where created by Parallel.Invoke to the one that called it in the first place. Is it normal that control does not revert to the thread where it started? And how can I assure that this does happen?
Code:
public void TopMethod()
{
Calculate(4);
UpdateGui();
}
public void Calculate(int depth)
{
Recursive(depth);
}
public void Recursive(int depth)
{
if (depth > 0)
System.Threading.Tasks.Parallel.Invoke(
delegate { Recursive(depth - 1); });
}
public void UpdateGui()
{
CalculateOhter(); // Works fine.
controlElement.Focus(); // Causes exception
}
Edits:
I know about Control.Invoke But this would be an ugly solution (don't want to store a delegate in every control) and the program needs to wait for all computations to complete before it can continue. So it would be better if I could somehow force control to return to the thread that I started out with in the first place.
You need to access a control/window from the thread that created that control. Use Control.Invoke and Control.InvokeRequired.
The horrible way to do is to set Control.CheckForIllegalCrossThreadCalls to false. It should get rid of your error, but it is not good design.
The problem with that occurs when a thread other than the creating thread of a control tries to access one of that control's methods or properties, it often leads to unpredictable results.
The example for Control.Invoke involves storing a Delegate, can this be done without storing a delegate for every control? So passing the method I need to call as an argument to the Invoke call (tried this but cannot get it to work).
The program needs to wait for all computations to complete before it can continue so it would be better if I could somehow force control to return to the thread that I started out with in the first place.
I don't understand why this does not happen at default, why does it not just return to the thread it started with when everything is complete?
Solved it, turns out I created a seperate thread to call the given code in the first place, kinda stupid :P
While going through this article I came across this statement -
If you are writing your own WPF
objects, such as controls, all methods
you use should call VerifyAccess
before they perform any work. This
guarantees that your objects are only
used on the UI thread, like this
//Using VerifyAccess and CheckAccess
public class MyWpfObject : DispatcherObject
{
public void DoSomething()
{
VerifyAccess();
// Do some work
}
public void DoSomethingElse()
{
if (CheckAccess())
{
// Something, only if called
// on the right thread
}
}
}
I haven't seen this in any of the custom controls I have come across(as far as I remember).
Do you use this while building custom controls?
Is it must to do this or just nice to have?
Anyone ever faced any issue due to absence of this in your controls?
Nah, never used this. And never noticed somebody use it in the context of Custom Controls. This rule is not followed in WPF Toolkit too.
This approach not only pollutes the code but also makes your custom control responsible for something it shouldn't care about. Consider situation where you always doing:
// Don't do this in all methods of your custom control!
public void Foo()
{
if (!CheckAccess())
{
Dispatcher.Invoke(()=> Foo()); // Transit to UI Thread
return;
}
// .. do work in UI.
}
At first glance this code looks fine. If you are not in UI thread, transit to UI thread, perform operation and return result. Right? - WRONG!
Problem 1. When you call Dispatcher.Invoke() you block calling thread until your request is processed by UI thread. This leads to poor performance. Of course, you can change this to Dispatcher.BeginInvoke() now your clients should be aware that their operation is done asynchronously. I.e. if client writes something to control, and then immediately reads it back there is no guarantee, that the operation already executed by UI thread.
Problem 2. Consider subsequent calls to the method Foo() from non UI thread. For example it's called in cycle:
// Somewhere not in UI
for (int i = 0; i < 1000000; i++)
{
control.Foo(); // Looks good, but performance is awful!
}
Instead of blocking calling thread 1000000 times, developer could implement one check in the calling thread and transit to UI when necessary, instead of unconsciously jumping back and worth between threads.
Furthermore WPF will make this check for you when you access UI element from non-UI thread. It screams loud enough to crush application and be heard by developer who has done something wrong :).
Hope this helps.
I have a program with a Geospace map embedded into it. The event handling for the map is handled on a separate thread to keep the map responsive (for example, the events that fire when the map is clicked).
The problem I am having is when the map fires an event, my program needs to update some things in it's gui, and also call back into the map to handle placing pictures on the map.
I tried wrapping the entire event handler method in this.Dispatcher.Invoke, which puts me back on the main UI thread. This works great for updating my GUI, but when i call back into the map, I'm still on the UI thread which can cause some problems in the map.
Basically, in order to make this work, I'm going to have to run dispatcher.invoke each time I want to change a control on my gui. Is there a way I can automatically do this without wrapping each call in dispatcher.invoke? I hope this all makes sense.
Heres some example code for the event I'm talking about..
private void Map_OnMapClicked(object sender, MapClickedEventArgs e)
{
this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
// Do something to update my gui
}));
Map.DoSomethingInTheMap();
this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
// Do something to update my gui
}));
//etc etc etc
}
If you need to keep each respective operation in its own synchronization context, this is unfortunately the best approach. You'll need to Invoke using the Dispatcher whenever you update your GUI.
Here are a couple of suggestions for making this easier:
Try to batch your GUI operations. In addition to requiring less code (via less invoke calls), you'll get better performance. Each Dispatcher.Invoke call carries a fair amount of overhead, since it posts a message into the Dispatcher's message queue which must be processed.
Consider using Dispatcher.BeginInvoke to avoid blocking, unless you really need to wait.
If you can use the Task Parallel Library from .NET 4 (or the backport to 3.5sp1 in the Rx Framework), you might want to consider reworking this to use Task instances synchronized to the GUI thread. By creating a TaskScheduler using FromCurrentSynchronizationContext, you can schedule tasks to run on the GUI easier than the Dispatcher Invoke calls. This also can give you some control over batching, since you can schedule them, and block/wait as needed, very easily.
You could use something like PostSharp or try to condense your UI updates to single method calls where you invoke once and do a lot. Or even a pattern like this (it's Winforms but the idea is the same):
private void UpdateToolStripItemText(ToolStripItem toolStripItem, string text)
{
if (InvokeRequired)
{
Invoke(new UpdateToolStripItemTextDelegate(UpdateToolStripItemText), new object[] { toolStripItem, text });
}
else
{
if (text != null)
{
toolStripItem.Text = text;
}
}
}
Let's say I have a C# program with a GUI, and the update/refresh/display of the GUI takes 0.2 seconds.
Say, while it is still computing the display process (within this 0.2 seconds), a new update request is given, so the current one is outdated. How can I make it stop doing this meaningless outdated work to start computing for the new request?
It might not be only about UI update too. Perhaps, for any function call, how can I make it so it will become "If another of the same call is issued, abandon the current work and go with the new data/situation instead"?
Thanks.
Perhaps, for any function call, how can I make it so it will become "If another of the same call is issued, abandon the current work and go with the new data/situation instead"?
Why would you want that? You would lose all provability in your code. You would never be able to ensure a consistent state in your system. If you want to simulate it, just mess with the PC. Design a program that arbitrarily pushes the PC back to the top of any method that it is in. You would quickly see the system devolve.
You're talking about some fairly advanced threading issues. Using the built-in system control structure, there's no way to prevent the message loop from completing any more than there is a method for interrupting (gracefully) another method.
Now, if this capability is very important to you, you COULD build all custom controls and within your control's painting code you could check (in a thread-safe manner, of course) a boolean value indicating whether or not painting should continue.
But if I can take a stab in the dark, I'm going to guess that you're not actually explicitly doing any multithreading. If this is the case, then the scenario that you describe can't ever actually happen, as the process of refreshing the GUI is going to complete before another one can begin (namely, this anonymous process you're describing that calls for another refresh or deems the current one stale). Because code on the same thread executes sequentially, there's really no opportunity for an unrelated piece of code to cause an update.
The semantics of how and when repaints take place (the difference between Invalidate() and Refresh(), and their respective impacts on this logic, for example) is a topic that's probably really not of interest to you. Just know that if you're...
Doing multithreading, then you'll
have to implement your own code for
checking whether or not the current
operation should continue (for the
UI, this means custom controls with
this logic in the paint logic)
Not
doing multithreading, then what you
describe can never happen.
Hope this is helpful!
One possible way is to start off a thread that updates the GUI and abort it and start another. This is generally not a recommended practice because of the horrible state of thread management in C# but you should be able to get around it without worrying.
public static class ControlExtensions
{
public static TResult InvokeEx<TControl, TResult>(this TControl control,
Func<TControl, TResult> func)
where TControl : Control
{
if (control.InvokeRequired)
return (TResult)control.Invoke(func, control);
else
return func(control);
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Thread guiUpdateThread = null;
public void BeginLongGuiUpdate(MyState state)
{
if (guiUpdateThread != null && guiUpdateThread.ThreadState != ThreadState.Stopped)
{
guiUpdateThread.Abort();
guiUpdateThread.Join(); // wait for thread to abort
}
guiUpdateThread = new Thread(LongGuiUpdate);
guiUpdateThread.Start(state);
}
private void LongGuiUpdate(object state)
{
MyState myState = state as MyState;
// ...
Thread.Sleep(200);
this.InvokeEx(f => f.Text = myState.NewTitle);
// ...
}
}
I don't knwo if this maps to what you need, but here goes.
One way to achieve this kind of behavior is to reverse the problem and delay the actual rendering.
Any time you get a request or change, fire off a timer. Every request coming in will either start or restart the time.
When the timer actually elapses, carry out the rendering.
It does not do exactly what you describe, but it might actually do what you need in the end, which is not to render for each request because rendering takes too long.
If you do not have continuous requests, this works fairly well. Obviously, if you do, you never get anything displayed...