Indeterminate ProgressBar animation jerk in Dispatcher.BeginInvoke - c#

I have a piece of code testing the GUI and threading behavior. I want to keep ProgressBar animation running (with IsIndeterminate="True") as I query the database and add a large number of rows (10K+) into the DataGrid. Even if I wrap the database and GUI code in Dispatcher.BeginInvoke, the ProgressBar animation would jerk as the DataGrid is being filled.
I would expect the ProgressBar animation would either freeze (if on GUI thread) or run smoothly (if on a separately thread), but I cannot understand why the animation is running jerkingly.
Please do not suggest BackgroundWorker, as I want to understand the problem in this question, and why BeginInvoke is not separating the threads. I simply loop through SqlDataReader and add to DataGrid as Item one by one instead of databinding to a source or a datatable.
// XAML
<Button Click="Button_Click"></Button>
<ProgressBar IsIndeterminate="True"></ProgressBar>
<DataGrid ... ></DataGrid>
// C#
private void Button_Click(object sendoer, RoutedEventArgs e)
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,(ThreadStart)delegate()
{
// Query database and update GUI (e.g. DataGrid)
});
}

The Dispatcher always executes code on the thread it is associated with (the UI thread in your case), regardless of whether you use Invoke or InvokeAsync (which is a convenient shorthand for BeginInvoke). So all the work regarding loading data from database and updating the DataGrid is done on UI thread, hence the animation is not smooth.
The difference between Invoke and InvokeAsync is that the former is executed synchronously, and the latter is executed asynchronously. What it means is that in the first case the calling thread will be suspended until the delegate has finished executing (i.e. it will be synchronized), whereas in the second case the thread will continue its execution without waiting for the delegate to finish. Let me try to point out this difference using examples.
Example I. The methods are called from the UI thread (as in your case)
Let's assume we only have one thread (the UI thread). Calling Invoke will not have any noticeable effect, since the delegate will be executed immediately and only then the execution will continue. So this:
Dispatcher.Invoke(() => DoSomeStuff());
DoSomeOtherStuff();
will have the same effect as this:
DoSomeStuff();
DoSomeOtherStuff();
Calling BeginInvoke however will have an effect such that the delegate will be scheduled to execute only after all scheduled tasks with higher priority (or already scheduled with the same priority) are executed. So in this case:
Dispatcher.InvokeAsync(() => DoSomeStuff());
DoSomeOtherStuff();
DoSomeOtherStuff() will be executed first, and DoSomeStuff() second. This is often used for example in event handlers where you need some code to be executed only after the event is completely handled (e.g. see this question).
Example II. The methods are called from a different thread
Let's assume we have two threads - the UI thread, and a worker thread. If we call Invoke from the worker thread:
Dispatcher.Invoke(() => DoSomeStuff());
DoSomeOtherStuff();
first DoSomeStuff() will be executed on UI thread, and then DoSomeOtherStuff() will be executed on worker thread. In case of InvokeAsync:
Dispatcher.InvokeAsync(() => DoSomeStuff());
DoSomeOtherStuff();
we only know that DoSomeStuff() will be executed on UI thread and DoSomeOtherStuff() will be executed on worker thread, but the order in which they will be executed is indeterminate*.
Usually Invoke is used when your delegate yields some result and you need it to continue execution on the worker thread (for example when you need to obtain a dependency property value). InvokeAsync on the other hand is usually used when the delegate does not yield any result (or the result is ignored), such as in your case - updating DataGrid does not yield any result worth waiting for so you can immediately continue to load the next batch of data.
I hope that sheds some light on the issue for you and you can see why the solution to "jerky UI" is to delegate heavy work to another thread and only use dispatcher to interact with UI. That's were suggestions to use BackgroundWorker or Task come from.
*Actually they probably will be executed simultaneously. What I meant was if for example both methods only print some text to console, the order of messages in the console is indeterminate.

Related

Dispatcher.Invoke on application idle on button click - does my UI freeze/block

Imagine you have some routine that registers as BeginInvoke to the ApplicationIdle, for example
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)OffLoadWork);
Now in certain scenarios this OffLoadWork needs to be executed when doing a operation in the UI, for example on a button click, is it safe for me to call
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.ApplicationIdle, (Func<object>)(() =>
{
//do nothing just wait for the OffLoadWork to happen...
return null;
}));
or can it occur that my UI freezes, since I am in the middle of an UI Operation so when does it actually get Idle?
In my first test, it seemed to work but I just want to make sure that there isn't a way for it to freeze/block.
I think you are confusing DispatcherPriority.ApplicationIdle. Invoke is sync and can block your UI.
DispatcherPriority here as per the definition is the priority, relative to the other pending operations in the Dispatcher event queue, the specified method is invoked. So if your operation is the only one happening in the Dispatcher queue and triggered on UI thread it will block it till the time it does not return.

What does SynchronizationContext do?

In the book Programming C#, it has some sample code about SynchronizationContext:
SynchronizationContext originalContext = SynchronizationContext.Current;
ThreadPool.QueueUserWorkItem(delegate {
string text = File.ReadAllText(#"c:\temp\log.txt");
originalContext.Post(delegate {
myTextBox.Text = text;
}, null);
});
I'm a beginner in threads, so please answer in detail.
First, I don't know what does context mean, what does the program save in the originalContext? And when the Post method is fired, what will the UI thread do?
If I ask some silly things, please correct me, thanks!
EDIT: For example, what if I just write myTextBox.Text = text; in the method, what's the difference?
What does SynchronizationContext do?
Simply put, SynchronizationContext represents a location "where" code might be executed. Delegates that are passed to its Send or Post method will then be invoked in that location. (Post is the non-blocking / asynchronous version of Send.)
Every thread can have a SynchronizationContext instance associated with it. The running thread can be associated with a synchronization context by calling the static SynchronizationContext.SetSynchronizationContext method, and the current context of the running thread can be queried via the SynchronizationContext.Current property.
Despite what I just wrote (each thread having an associated synchronization context), a SynchronizationContext does not necessarily represent a specific thread; it can also forward invocation of the delegates passed to it to any of several threads (e.g. to a ThreadPool worker thread), or (at least in theory) to a specific CPU core, or even to another network host. Where your delegates end up running is dependent on the type of SynchronizationContext used.
Windows Forms will install a WindowsFormsSynchronizationContext on the thread on which the first form is created. (This thread is commonly called "the UI thread".) This type of synchronization context invokes the delegates passed to it on exactly that thread. This is very useful since Windows Forms, like many other UI frameworks, only permits manipulation of controls on the same thread on which they were created.
What if I just write myTextBox.Text = text; in the method, what's the difference?
The code that you've passed to ThreadPool.QueueUserWorkItem will be run on a thread pool worker thread. That is, it will not execute on the thread on which your myTextBox was created, so Windows Forms will sooner or later (especially in Release builds) throw an exception, telling you that you may not access myTextBox from across another thread.
This is why you have to somehow "switch back" from the worker thread to the "UI thread" (where myTextBox was created) before that particular assignment. This is done as follows:
While you are still on the UI thread, capture Windows Forms' SynchronizationContext there, and store a reference to it in a variable (originalContext) for later use. You must query SynchronizationContext.Current at this point; if you queried it inside the code passed to ThreadPool.QueueUserWorkItem, you might get whatever synchronization context is associated with the thread pool's worker thread. Once you have stored a reference to Windows Forms' context, you can use it anywhere and at any time to "send" code to the UI thread.
Whenever you need to manipulate a UI element (but are not, or might not be, on the UI thread anymore), access Windows Forms' synchronization context via originalContext, and hand off the code that will manipulate the UI to either Send or Post.
Final remarks and hints:
What synchronization contexts won't do for you is telling you which code must run in a specific location / context, and which code can just be executed normally, without passing it to a SynchronizationContext. In order to decide that, you must know the rules and requirements of the framework you're programming against — Windows Forms in this case.
So remember this simple rule for Windows Forms: DO NOT access controls or forms from a thread other than the one that created them. If you must do this, use the SynchronizationContext mechanism as described above, or Control.BeginInvoke (which is a Windows Forms-specific way of doing exactly the same thing).
If you're programming against .NET 4.5 or later, you can make your life much easier by converting your code that explicitly uses SynchronizationContext, ThreadPool.QueueUserWorkItem, control.BeginInvoke, etc. over to the new async / await keywords and the Task Parallel Library (TPL), i.e. the API surrounding the Task and Task<TResult> classes. These will, to a very high degree, take care of capturing the UI thread's synchronization context, starting an asynchronous operation, then getting back onto the UI thread so you can process the operation's result.
I'd like to add to other answers, SynchronizationContext.Post just queues a callback for later execution on the target thread (normally during the next cycle of the target thread's message loop), and then execution continues on the calling thread. On the other hand, SynchronizationContext.Send tries to execute the callback on the target thread immediately, which blocks the calling thread and may result in deadlock. In both cases, there is a possibility for code reentrancy (entering a class method on the same thread of execution before the previous call to the same method has returned).
If you're familiar with Win32 programming model, a very close analogy would be PostMessage and SendMessage APIs, which you can call to dispatch a message from a thread different from the target window's one.
Here is a very good explanation of what synchronization contexts are:
It's All About the SynchronizationContext.
It stores the synchronization provider, a class derived from SynchronizationContext. In this case that will probably be an instance of WindowsFormsSynchronizationContext. That class uses the Control.Invoke() and Control.BeginInvoke() methods to implement the Send() and Post() methods. Or it can be DispatcherSynchronizationContext, it uses Dispatcher.Invoke() and BeginInvoke(). In a Winforms or WPF app, that provider is automatically installed as soon as you create a window.
When you run code on another thread, like the thread-pool thread used in the snippet, then you have to be careful that you don't directly use objects that are thread-unsafe. Like any user interface object, you must update the TextBox.Text property from the thread that created the TextBox. The Post() method ensures that the delegate target runs on that thread.
Beware that this snippet is a bit dangerous, it will only work correctly when you call it from the UI thread. SynchronizationContext.Current has different values in different threads. Only the UI thread has a usable value. And is the reason the code had to copy it. A more readable and safer way to do it, in a Winforms app:
ThreadPool.QueueUserWorkItem(delegate {
string text = File.ReadAllText(#"c:\temp\log.txt");
myTextBox.BeginInvoke(new Action(() => {
myTextBox.Text = text;
}));
});
Which has the advantage that it works when called from any thread. The advantage of using SynchronizationContext.Current is that it still works whether the code is used in Winforms or WPF, it matters in a library. This is certainly not a good example of such code, you always know what kind of TextBox you have here so you always know whether to use Control.BeginInvoke or Dispatcher.BeginInvoke. Actually using SynchronizationContext.Current is not that common.
The book is trying to teach you about threading, so using this flawed example is okayish. In real life, in the few cases where you might consider using SynchronizationContext.Current, you'd still leave it up to C#'s async/await keywords or TaskScheduler.FromCurrentSynchronizationContext() to do it for you. But do note that they still misbehave the way the snippet does when you use them on the wrong thread, for the exact same reason. A very common question around here, the extra level of abstraction is useful but makes it harder to figure out why they don't work correctly. Hopefully the book also tells you when not to use it :)
The purpose of the synchronization context here is to make sure that myTextbox.Text = text; gets called on the main UI thread.
Windows requires that GUI controls be accessed only by the thread they were created with. If you try assign the text in a background thread without first synchronizing (through any of several means, such as this or the Invoke pattern) then an exception will be thrown.
What this does is save the synchronization context prior to creating the background thread, then the background thread uses the context.Post method execute the GUI code.
Yes, the code you've shown is basically useless. Why create a background thread, only to immediately need to go back to the main UI thread? It's just an example.
SynchronizationContext basically is a provider of callback delegates' execution. It is responsible for ensuring that the delegates are run in a given execution context after a particular portion of code (encapsulated inside a Task object in .Net TPL) in a program has completed its execution.
From technical point of view, SC is a simple C# class that is oriented to support and provide its function specifically for Task Parallel Library objects.
Every .Net application except for console applications has a tailored implementation of this class based on the specific underlying framework, eg: WPF, WindowsForm, Asp Net, Silverlight, etc.
The importance of this object is bound to the synchronization between results returning from asynchronous execution of code, and the execution of dependent code that is waiting for results from that asynchronous work.
And the word "context" stands for execution context. That is, the current execution context where that waiting code will be executed- namely the synchronization between async code and its waiting code happens in a specific execution context. Thus this object is named SynchronizationContext.
It represents the execution context that will look after syncronization of async code and waiting code execution.
To the Source
Every thread has a context associated with it -- this is also known as the "current" context -- and these contexts can be shared across threads. The ExecutionContext contains relevant metadata of the current environment or context in which the program is in execution. The SynchronizationContext represents an abstraction -- it denotes the location where your application's code is executed.
A SynchronizationContext enables you to queue a task onto another context. Note that every thread can have its own SynchronizatonContext.
For example: Suppose you have two threads, Thread1 and Thread2. Say, Thread1 is doing some work, and then Thread1 wishes to execute code on Thread2. One possible way to do it is to ask Thread2 for its SynchronizationContext object, give it to Thread1, and then Thread1 can call SynchronizationContext.Send to execute the code on Thread2.
SynchronizationContext provides us a way to update a UI from a different thread (synchronously via the Send method or asynchronously via the Post method).
Take a look at the following example:
private void SynchronizationContext SyncContext = SynchronizationContext.Current;
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread thread = new Thread(Work1);
thread.Start(SyncContext);
}
private void Work1(object state)
{
SynchronizationContext syncContext = state as SynchronizationContext;
syncContext.Post(UpdateTextBox, syncContext);
}
private void UpdateTextBox(object state)
{
Thread.Sleep(1000);
string text = File.ReadAllText(#"c:\temp\log.txt");
myTextBox.Text = text;
}
SynchronizationContext.Current will return the UI thread's sync context. How do I know this? At the start of every form or WPF app, the context will be set on the UI thread. If you create a WPF app and run my example, you'll see that when you click the button, it sleeps for roughly 1 second, then it will show the file's content. You might expect it won't because the caller of UpdateTextBox method (which is Work1) is a method passed to a Thread, therefore it should sleep that thread not the main UI thread, NOPE! Even though Work1 method is passed to a thread, notice that it also accepts an object which is the SyncContext. If you look at it, you'll see that the UpdateTextBox method is executed through the syncContext.Post method and not the Work1 method. Take a look at the following:
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread.Sleep(1000);
string text = File.ReadAllText(#"c:\temp\log.txt");
myTextBox.Text = text;
}
The last example and this one executes the same. Both doesn't block the UI while it does it jobs.
In conclusion, think of SynchronizationContext as a thread. It's not a thread, it defines a thread (Note that not all thread has a SyncContext). Whenever we call the Post or Send method on it to update a UI, it's just like updating the UI normally from the main UI thread. If, for some reasons, you need to update the UI from a different thread, make sure that thread has the main UI thread's SyncContext and just call the Send or Post method on it with the method that you want to execute and you're all set.
Hope this helps you, mate!
This example is from Linqpad examples from Joseph Albahari but it really helps in understanding what Synchronization context does.
void WaitForTwoSecondsAsync (Action continuation)
{
continuation.Dump();
var syncContext = AsyncOperationManager.SynchronizationContext;
new Timer (_ => syncContext.Post (o => continuation(), _)).Change (2000, -1);
}
void Main()
{
Util.CreateSynchronizationContext();
("Waiting on thread " + Thread.CurrentThread.ManagedThreadId).Dump();
for (int i = 0; i < 10; i++)
WaitForTwoSecondsAsync (() => ("Done on thread " + Thread.CurrentThread.ManagedThreadId).Dump());
}

Update WPF GUi while Parallel.ForEach

I Have a WPF multithread application, and each thread updates some variables of objects binding to the xaml gui.
If I Use a normal thread or a threadpool it works fine. Each object is being updated at real time in the GUI when the object variables is changed by the treads.
I want to use Parallel.ForEach because it stops the execution util all threads are finished. This is important to me for block the interface (because the use should wait), and for can show a finished message. The bad thing is that with Parallel.Foreach is not being updated in real time, only when all threads are finished.
This way works, but It only updates the Gui at the end.
Parallel.ForEach(Computers, new ParallelOptions { MaxDegreeOfParallelism = 1}, computer => { PingTemp(computer); });
This way works, but It doesn't wait to the end of the ThreadPool.
Task.Factory.StartNew(() => Parallel.ForEach<Computer>(Computers, new ParallelOptions { MaxDegreeOfParallelism = 1 }, computer => PingTemp(computer)));
What approach do you recommend when the GUI is updated in realtime and wait the execution of threadpool before continue.
Do NOT do that in the same thread. If you need the user to wait, then use a mechanism where you LOGICALLY stop interaction at the UI (turn if ff, put a transparent label with a working animation on top of the window) and do things outside the loop. The whole UI interaction is blocked as long as your thread blocks.
YOu do NOT get ANY updates in the UI while the UI thread is blocking. So, that already kills what you want. But more important - you really make bad things. ALWAYS keep the UI free.
My old rule is 0.1/1. Everything longer than 0.1 seconds MUST go into a non-ui thread, anything longer than 1 second MUST disable the UI and show a working animation, preferably one that shows progress if feasible by any mreans.
I use a GUI framework that handles that automatically via bound method signatures (telling the UI this method call is async, then the routine is automatically called in a separate thread).

c# async calls UI not responding

This is my requirement:
On a button click I need to get the data from database and populate in a datagridview, for which I'm using a function. As the retrieval may take a long time and I want to use the UI meanwhile, I want this function to run in a separate thread.
For this, I'm using async callback. But between the begininvoke() and endinvoke() function. I'm not writing any code (I don't know what to write to make the UI respond).
The datagridview is getting populated correctly but the UI is blocked when I'm trying to access it when the function is retrieving the data.
I'd recommend not to start the long running operation from the UI thread. Start another thread first, and then do the long running operation in that separate thread. When it is done, post the results back to the UI using the Form.Invoke() method. This way, the UI thread is not affected directly.
Instead of creating another thread by hand, you can also use a construct like BackgroundWorker.
If you do start the long running operation from the UI thread, you'd need to call Application.DoEvents() periodically (e.g. inside a loop). However, if the long running operation is an IO intensive -- meaning you are waiting for an IO operation most of the time -- then you won't get to call Application.DoEvents() as often as you'd like. This will make the UI seem less responsive or jerky. The seperate thread, as I mentioned above, is a better way in this regard.
If you are using a loop to Populate your DataGridView, You can use the Method Application.DoEvents() inside your loop to make your UI remain Responsive during the population of the DataGridView.
Update
As you stated the problem is not the loop, I think the best approach will be using the BackgroundWorker class.
Where you can populate the DataGridView in the DoWork() event of the BackgroundWorker
And you can start the BackgroundWorker.DoWork() event during the button_click event of your Code!
First of all, i should create asynccallback function in the UI form itself, not in middle level which is, in my case , DataMgr.
Also, i should add the last two parameters for begininvoke function with appropriate values where i have passed null values.
It should be
MethodDelegate dlgt = new MethodDelegate(DataMgr.countIssuingEntities);
TempValueHolder tmp = new TempValueHolder();
AsyncCallback cb = new AsyncCallback(MyAsyncCallBack);
IAsyncResult ar = dlgt.BeginInvoke(issueGroupId, element.ControlType, (EvaluatingEntityCombo.SelectedItem as CIQHydCore.RefData.RefDataInfo).Id, (IssuingEntityCombo.SelectedItem as CIQHydCore.RefData.RefDataInfo).Id, str1, str2,**cb,dlgt**);
and in MyAsyncCallBack function we need to populate the datgridview with the retrieved values from the end

How to check if Thread finished execution

I have following problem:
I want to check (C#) if a thread has finished execution, i.e. if the thread method has returned. What I do now is call Thread.Join(1), but this gives a 1 ms delay. Is there any way to simply check if a thread has finished. Inspecting Thread.ThreadState just seems too cumbersome.
Use the Thread.IsAlive flag. This is to give the thread status.
For a thread you have the myThread.IsAlive property. It is false if the thread method returned or the thread was aborted.
If you don't want to block the current thread by waiting/checking for the other running thread completion, you can
implement callback method like this.
Action onCompleted = () =>
{
//On complete action
};
var thread = new Thread(
() =>
{
try
{
// Do your work
}
finally
{
onCompleted();
}
});
thread.Start();
If you are dealing with controls that doesn't support cross-thread operation, then you have to invoke the callback method
this.Invoke(onCompleted);
You could fire an event from your thread when it finishes and subscribe to that.
Alternatively you can call Thread.Join() without any arguments:
Blocks the calling thread until a thread terminates, while continuing to perform standard COM and SendMessage pumping.
Thread.Join(1) will:
Blocks the calling thread until a thread terminates or the specified time elapses, while continuing to perform standard COM and SendMessage pumping.
In this case the specified time is 1 millisecond.
Use Thread.Join(TimeSpan.Zero) It will not block the caller and returns a value indicating whether the thread has completed its work. By the way, that is the standard way of testing all WaitHandle classes as well.
I use IsAlive extensively, unless I want to block the current execution (of the calling thread), in which case I just call Join() without a parameter. Now, be aware that IsAlive may return false if the target thread has not actually started execution yet for any reason.
Carlos Merighe.
It depends on how you want to use it. Using a Join is one way. Another way of doing it is let the thread notify the caller of the thread by using an event. For instance when you have your graphical user interface (GUI) thread that calls a process which runs for a while and needs to update the GUI when it finishes, you can use the event to do this. This website gives you an idea about how to work with events:
http://msdn.microsoft.com/en-us/library/aa645739%28VS.71%29.aspx
Remember that it will result in cross-threading operations and in case you want to update the GUI from another thread, you will have to use the Invoke method of the control which you want to update.
Take a look at BackgroundWorker Class, with the OnRunWorkerCompleted you can do it.

Categories