Update WPF GUi while Parallel.ForEach - c#

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).

Related

Xamarin.iOS main and background threads not playing nice

I will try and keep this short and sweet.
I have this code which is a result of a button being pressed (so its on the main UI thread)
MessageCenter.Init();
the above method does this (as well as other things)
NS = NSTimer.CreateRepeatingScheduledTimer(TimeSpan.Parse("00:00:30"), delegate
{
NSObject.InvokeInBackground(() =>
{
HandleElapsed();
});
});
HandleElapsed(); obtains an exclusive lock on an object using the Monitor.Enter(obj) method. mean while the main ui thread also may need to obtain an exclusive lock. (the lock is in place to ensure sqlite data integrity)
when the main UI encounters a lock on the object (i.e its already locked) the entire app just halts (including the background thread)
I should mention the UI may need to get a lock when its told to change its content. HandleElapsed(); will ask the main UI thread to change its content.
NSNotificationCenter.DefaultCenter.PostNotificationName("ChangeDetail", new NSString("News"));
please note the change in contents is completed on the main thread
UIApplication.SharedApplication.InvokeOnMainThread();
its seems when the main ui is stuck on a lock... its also doesn't allow the background thread to continue thus the background thread is not able to move on a call to Monitor.Exit();
am i missing something?
Solved it.
I kept the database open throughout. and simply applied the locking mechanism
lock(SQLight.Connection)
{
...
}
this means all my threads uses the same connection but each thread can only interact with the data in turn.
This seems to have achieved what I wanted

Waiting until a timer runs out and executing another timer

I'll be short and to the point. I basically need a way I can take a timer, check when the timer is up and execute something at the end of it, then loop it. For example (this code isn't serious, just example code) :
Timer1.start();
If (timer1.TimeRanOut) {
Timer2.start()
}
Or some other way to pause the timer without the GUI freezing up (I'll be running some things at a fast pace and freezing would get in the way). I'll be making this more complex by looping the entire process, like :
if (Checkbox1.checked == true; )
{
Timer1.start();
Next If (timer1.TimeRanOut) {
Timer2.start()
}
Next If (timer2.TimeRanOut) {
Timer3.start()
}
And so on. Any solutions?
I would suggset working with Tasks. you set up a task to do something (it can just wait for X seconds, than it is a timer) than you set continueWith to assign a new task to run when the first one is finshed.
You can read more about this here:
http://msdn.microsoft.com/en-us/library/dd537612.aspx
And by the way, you really should not run heavy calculations on the UI thread itself.
If you decide to use tasks - that would be fine. Otherwise , you need to create background thread and do the work there.
Edit:
After some clarification from the OP , I will try to explain the basics or working with UI and background threads:
When you run a winforms/WPF application, all of the user interface events are handled in a single thread - the UI thread. it goes over all of the events and processes them.
If long calculation occupy this thread, the UI will become "stuck" and o responsive. see:
UI freezes on heavy calculation
That is why, any long calculations should be done on another thread, in the background.
In the above post's answer there is an example on how to do this.
You could use the System.Threading.Timer. You would then make use of its single shot capability (see Change method). Such you may chain several timers.
The callback of this timer runs on the thread pool so your UI doesn't freeze.

What is the best way to use threads for database operations?

I'm developing a WinForms application with SQL Compact as main database. I was told i would NEVER mess with the UI Thread, every operation needs to be done outside the UI Thread.. going by this speech for every CRUD operation I create a thread and a progress bar appears, but I think this might not be the best way to do this, and I'm quite unsure of where and when to use threads along side with database operations. I'm not using the UI Thread to make these DB calls but i'm not seeing any problems if i would. To show the information to the user i make Invokes when needed (to show data on a grid or a combobox). Here is a small piece of code:
this.SuspendLayout();
ProgressDialog progressDialog = new ProgressDialog();
Thread backgroundThread = new Thread(
new ThreadStart(() =>
{
var unitOfWork = new DAL.Implementations.Entity_Framework.UnitOfWork<dbgmEntities>();
var espacosRepository = unitOfWork.GetRepository<DAL.Espacos>();
Espacos espaco;
if (e.Row.Cells["ESP_Descr"].Value != null)
espaco = new Espacos { ESP_Nome = e.Row.Cells["ESP_Nome"].Value.ToString(), ESP_Descr = e.Row.Cells["ESP_Descr"].Value.ToString() };
else
espaco = new Espacos { ESP_Nome = e.Row.Cells["ESP_Nome"].Value.ToString() };
espacosRepository.AddOrAttach(espaco);
unitOfWork.Save();
}
));
backgroundThread.Start();
progressDialog.Show();
progressDialog.Close();
this.ResumeLayout();
I'm using Repository Pattern with SQL Compact and Entity Framework 4.0, as you can see i do database operations inside threads and not on the UI Thread which would block the user interface if it was a heavy operation.. the question is:
Is it really necessary to make database calls from a thread outside the UI Thread or just a heavy operation? Like adding more than 1 or 2 rows on different tables.
Thanks
The UI thread really should just be used to display things to the user and process input events from the user. Anything else should be delgated to a worker thread. That includes database operations. The issue is that long-running processes tie up the main thread so that it is unable to do anything else for the duration of the process. Since it's hard to guarantee that your database operation is going to come back quickly, it's probably not a good idea to have operations that access it be on the main thread.
Keep in mind that this is just a guideline. If whatever work you're performing takes a very small amount of time, it's not worth it to spin up a new thread. Spinning up a new thread costs you CPU cycles as well, so it might not be worth it to do that work on another thread.
Some recommendations:
Don't instantiate threads directly; use the thread pool instead: ThreadPool.QueueUserWorkItem
Don't immediately close your progress bar. Show it, and then invoke the call to hide it from the worker thread after your database operation is complete.
This is a good article on the thread pool.
As Dan said, the UI thread should be used simply for displaying things and getting user input.
However, the vast majority of operations we tend to do are extremely fast. To the point that spinning up another thread adds more to the time cost than simply performing the operation itself. My suggestion is that you only spin up a new thread for anything which will take more than a few seconds to process.

Creating rows in a datagridview using Parallel.ForEach

Recently decided to write a "quick" windows form app to tag my MP3 files. Not done anything with parallelism since .Net 3.0, so I'm looking at the Parallel.ForEach method to deal with the UI locking I get when I'm using a standard foreach statement. Here's an excerpt:
var i = 1;
var files = new List<string>(); // File list is populated using recursive method.
foreach(var f in files) {
// Add a row
var row = dgvList.Rows[dgvList.Rows.Add()];
// Update label
lblSummary.Text = string.Concat("Processing... ", i);
// Do things with row
// Increment progress bar
progressBar.PerformStep();
i++;
}
I've figured out the simple usage of Parallel.ForEach(), but I'm not sure I should be using that particular method to update the UI? Any suggestions?
You shouldn't use Parallel Libraries from your UI thread. The parallel library runs a group of tasks on multiple threads so you shouldn't write any UI related code inside it.
What you should do is move your business logic to background tasks and update the UI using dispatcher that will execute it on UI thread
as MSDN says
It is important to keep your application's user interface (UI) responsive. If an
operation contains enough work to warrant parallelization, then it likely should not
be run that operation on the UI thread. Instead, it should offload that operation to
be run on a background thread. For example, if you want to use a parallel loop to
compute some data that should then be rendered into a UI control, you should consider
executing the loop within a task instance rather than directly in a UI event handler.
Only when the core computation has completed should you then marshal the UI update back
to the UI thread.
and most importantly if you try to update UI thread from Paralle.Foreach
If you do run parallel loops on the UI thread, be careful to avoid updating UI
controls from within the loop. Attempting to update UI controls from within a parallel
loop that is executing on the UI thread can lead to state corruption, exceptions,
delayed updates, and even deadlocks, depending on how the UI update is invoked
You should be very careful with thread-safety.
You should be make sure to lock any object you are using, and unlock it appropriately.
Otherwise, there should be no problem I know of using Parallel.ForEach for UI.
EDIT: you can set Form.CheckForIllegalCrossThreadCalls=false to disable check for thread-safety.
Here's some documentation: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.checkforillegalcrossthreadcalls.aspx
This will work, but it is dangerous, because then you need to care about your thread-safety by yourself.
A better way to deal with this is to use the invoke-pattern for the UI-logic, but then parallelism will suffer, as the UI operation itself will be called on the UI thread.
It is, however, the safe way to do things.
Documentation: http://msdn.microsoft.com/en-us/library/ms171728.aspx
OK, I found the best way to achieve this is by running something like this:
// Kick off thread
Task.Factory.StartNew(delegate{
foreach(var x in files) {
// Do stuff
// Update calling thread's UI
Invoke((Action)(() => {
progressBar.PerformStep();
}));
}
}
I actually updated my code to populate a List within the foreach loop, then assign that to the daragrid via .DataSource, instead of working with the .Rows collection directly. Should have done that from the start really :)

Busy waiting in C#

How do you implement busy waiting in a not total inefficient way? I am facing the issue that I can load the data of my model only in a pull manner, which means I have to invoke getXYZ() methods in a continuous way.
This has to happen not fast enough for user interaction, but fast enought, that when a state in the GUI is changed, the model can be noticed and the new state is received by the getXYZ() methods.
My approach simply be:
while (c.hasChanged()) {
Thread.sleep(500);
}
updateData();
Are there better mechanisms?
Your problem seems to be solvable with Threading.
In WPF you can do:
Thread t = new Thread((ThreadStart)delegate() {
while (true) {
Thread.sleep(500);
if (c.hasChanged())
Dispatcher.Invoke((Action)delegate() {updateData();});
}
}).Start();
In WinForms
Thread t = new Thread((ThreadStart)delegate() {
while (true) {
Thread.sleep(500);
// this must derive from Control
if (c.hasChanged())
this.Invoke((Action)delegate() {updateData();});
}
}).Start();
There may be missing parameters to Invoke (which is needed to execute the code on the calling UI thread) but I'm writing this from my brain so no intellisense at disposal :D
In .NET 4 you can use TaskFactory.StartNew instead of spawning a thread by yourself.
In .Net <= 4, you could use the TreadPool for the thread.
However I recall you need this to be run at once because you expect it to be there checking as soon as possible and the thread pool won't assure you that (it could be already full, but not very likely:-).
Just don't do silly things like spawning more of them in a loop!
And inside the thread you should put a check like
while (!Closing)
so that the thread can finish when you need it without having to resort to bad things like t.Abort();
An when exiting put the Closing to true and do a t.Join() to close the checker thread.
EDIT:
I forgot to say that the Closing should be a bool property or a VOLATILE boolean, not a simple boolean, because you won't be ensured that the thread could ever finish (well it would in case you are closing the application, but it is good practice to make them finish by your will). the volatile keyword is intended to prevent the (pseudo)compiler from applying any optimizations on the code that assume values of variables cannot change
It's not clear from your post exactly what you are trying to do, but it sounds like you should put your model/service calls on a separate thread (via Background worker or async delegate) and use a callback from the model/service call to notify the UI when it's done. Your UI thread can then do busy things, like show a progress bar, but not become unresponsive.
If you are polling from a GUI, use a (WinForms) Timer.
If this is some kind of background process, your Sleep() may be the lesser evil.
Explicit busy waiting is evil and must be avoided whenever possible.
If you cannot avoid it, then build your application using the Observer design pattern and register the interested objects to an object which performs the polling, backed by a thread.
That way you have a clean design, confining the ugly stuff in just one place.

Categories