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.
Related
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
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).
I wrote some C# code and in it I initiate a class by placing it in its own thread so it doesnt freeze up my GUI from where I initiate it:
This is from my Form Class:
Execute_Recipe execute;
execute = new Execute_Recipe(XCoordinatesList, YCoordinatesList, Zref, Voltref,
widget, record, filename);
Thread executethread = new Thread(new ThreadStart(execute.RunRecipe));
And then in my Execute Class I create a new class to record the data. This is from my execute class:
record1 = new Record_Recipe(XCoordinateList1, YCoordinateList1, Zref1, Voltref1, filename1);
And finally in my record class I send the data to a new form. To be displayd. So in the end all of the sub classes I initiate are all created within this thread. I know the structure is absolutley crazy right now, the software is deep in its development stage, but here is my question:
How can I keep BOTH Form Classes in their own threads while having all the execution and recording of my procedure in its own thread?
Do I create 1 thread for my execution, 1 thread for my recording, and a backgrounworker for my displaying? and then talk between threads? (from what I understand talking between threads is not easy)
I am only an intermediate programmer at best and I thank you in advance if you able / willing to help with this problem.
Talking between threads is very easy in C#
yourform.BeginInvoke((MethodInvoker)delegate()
{
yourform.button.Text = "new label";
//More stuff here
});
kind of construct can be used from a worker thread to updated the UI thread. If you are creating lot of non UI threads that have smaller lifetime consider using a ThreadPool instead.
For simple ui updates also look at INotifyPropertyChanged that lets you updated data bound controls easily.
The thread you call Application.Run() on is the thread that must do all the GUI stuff. The Windows.Forms.Control base class has an Invoke() method that allows a delegate to be called whenever the GUI thread is idle (a Form is such a Control). There are quite a few other mechanisms in .NET to communicate between threads.
Communicating to a non-GUI thread is a bit getting used to, but there are quite a few options. An example of for instance using the WaitHandle is as follows:
receiving thread waits for a signal
sending thread writes data
sending thread sets signal
receiving thread reads data and performs the task
Usually one thread ("the main thread") leads and the others either wait for work, or are created, do the work and are destroyed afterwards.
I suggest you check the System.Threading namespace on MSDN and see what's available. Also http://www.albahari.com/threading/ seems to cover it all.
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.
What do I want to achieve: I want to perform some time consuming operations from my MDI winforms application (C# - .NET).
An MDI child form may create the thread with the operation, which may take long time (from 0.1 seconds, to even half hour) to complete. In the meantime I want the UI to respond to user actions, including manipulation of data in some other MDI child form. When the operation completes, the thread should notify the MDI child that the calculations are done,
so that the MDI child can perform the post-processing.
How can I achieve this:
Should I use explicit threading (i.e., create explicit threads), thread pools? Or simply just propose your solution. Should I create foreground or background threads?
And how does the thread communicates with the GUI, according the solution you propose?
If you know of a working example that handles a similar situation, please make a note.
I think you are looking for the BackgroundWorker class. Example
Use the BackgroundWorker class. It does just what you're looking for:
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(LongRunningCode);
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CallbackOnCompletion);
backgroundWorker.RunWorkerAsync();
Also, to update your UI from the background thread, you need to call Invoke on your UI element.
This depends, slightly.
In general, I agree with BFree that the BackgroundWorker is likely the best option here. I makes notification back to the UI simple, etc.
That being said, the only reason I'm posting, and questioning whether you may want to use BackgroundWorker is this statement:
which may take long time (from 0.1 seconds, to even half hour) to complete
BackgroundWorker uses a ThreadPool thread to perform its processing. This means that closing your Application form will terminate the thread, since it's a background thread.
If your "half hour" processing "work" is something that you would like to have continue operating, even if the form is closed, you may want to make your own foreground thread to perform this operation, and handle the UI marshaling yourself.
While the BackgroundWorker object is an obvious choice, it may not be advisable for a lengthy process, as it uses the ThreadPool. The conventional wisdom around the ThreadPool is that it shouldn't be used for long-running tasks; in these cases explicit thread creation is advisable.
You can still interact with the GUI by calling Invoke or BeginInvoke on the form (or any of its controls), passing in a delegate that will perform the GUI-related actions.
If you have a very finite number of threads (let's say, at most 4), then you can create them yourself. If you need them to be managed in a way that you don't want to deal with it, then a threadpool is one option or .NET 4.0's System.Threading.Tasks namespace.
You'll probably need to use delegates. Here's an example of one that writes to the UI and one that reads from the UI:
delegate void SetResultsTextCallback(string text);
delegate string GetIterationCountCallback();
private void SetResultsText(string text)
{
if (this.ResultsBox.InvokeRequired)
{
var d = new SetResultsTextCallback(SetResultsText);
this.Invoke(d, new object[] { text });
}
else
{
this.ResultsBox.Text = text;
}
}
private string GetIterationCount()
{
if (this.RepetitionSelector.InvokeRequired)
{
var del = new GetIterationCountCallback(GetIterationCount);
IAsyncResult result = del.BeginInvoke(null, null);
return del.EndInvoke(result);
}
else
{
return RepetitionSelector.SelectedItem.ToString();
}
}
In this example, ResultsBox is a TextBox and RepetitionSelector is a combobox.
You have many options:
Use BackgroundWorker directly which basically does most of the work for you, but the lengthy operation must be known by the UI.
Inherit from System.ComponentModel.BackgroundWorker which enables to use the operation as a component and separate the logic from the UI.
Use the Event-based pattern, which would allow greater control for the parameters and events raised.
Use the delegates, if there is really nothing to report but the ned of the operation. You must have caution as the callback method is not guaranteed to run in the UI thread.
I recommend creating a thread and using a callback method to communicate with the UI.
I give an example in this solution, where you'll also find examples for other approaches: .NET Threading & Locks & Waiting.