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
Related
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 see a lot of threads on google/here on UPDATING a UI element from another thread.
What if I want to just get the value of a checkbox?
Am I able to do this without having to do anything special?
Edit: It seems I have to take back what I wrote before. Tried the following:
Added a textbox called myTextBox and tried to retrieve the value of the Text property:
Thread t = new Thread(
o =>
{
Thread.Sleep(2000);
string value = myTextBox.Text;
Thread.Sleep(2000);
});
t.Start();
And it seems that the app (WPF) crashes after 2 seconds. Using the dispatcher works:
Thread t = new Thread(
o =>
{
Thread.Sleep(2000);
myTextBox.Dispatcher.BeginInvoke(
(Action)(() => { string value = myTextBox.Text; }));
Thread.Sleep(2000);
});
t.Start();
Thus, you still need to go through the dispatcher thread when reading values from GUI components, at least in WPF.
Second edit: This gets better. Apparently repeating the experiment for classic WinForms reveals that it works to read the Text property without using Invoke/BeginInvoke. Interestingly enough, it seems that also setting the property works fine (without invoke), although I'll wager it's not thread safe and the app doesn't complain for some reason.
Bottom line: It's a good idea in any case to use the dispatcher when interacting with GUI components from other threads, as it ensures the reads/writes are serialized to a single thread and so you have no thread-safety issues.
Can you access UI elements from another thread? (get not set)?
No.
Here is the deal. UI elements have very strict thread affinity requirements. This means you can only access the element from the thread hosting it. This includes all kinds of accesses including simple reads.1
It may work fine for simple property getters, but its perceived safeness would be an accidental result of the way that particular control was implemented. Since Control instances have thread affinity they could potentially use thread local storage techniques to save some of their state which, of course, would not be compatible with different thread. Or what if the value you are trying to read is in a half-baked state? There would be no way to synchronize access to that read since the write may be occurring inside code you have no control over. And still this is ignoring subtle memory barrier problems that may arise.
Again, if it appears to work then chalk it up as an accident. Accessing UI elements from a thread than the one hosting them is a recipe for disaster. Things may fail unpredictably and spectacularly.
1There are very few exceptions to this rule. Using the ISynchronizeInvoke methods is one such exception.
You could but strictly it wouldn't be thread safe.
For instance if the property Get code would consist of multiple operations, the UI thread could act in the mean time, halfway during the Get operation, causing unexpected results.
simply read the value as you normally do. Only to update the control, you need to switch to GUI 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.
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 :)
I have a lot of long-running activities and think that spawning this activity off to another thread will be a good way to have my U.I be able to update to show its current status.
However, when I use the following:
Thread t = new Thread(() =>
{
/* do magic here */
});
Nothing inside the foreach loop that's inside the thread gets done. But, when I don't use a thread, the work does get done, so I know it's not a problem with the loop.
Any suggestions?
You may also want to take a look at BackgroundWorker as it nicely encapsulates everything.
Are you even starting the thread?
newThread.Start();
In the sample you provide you merely declare it.
Also bear in mind that if you're using WinForms, you won't be able to update the UI directly from any thread other than the one that created it; for example, modifying a progress bar or label control from within your foreach loop.
You need to start the tread, t.Start();
Creating the instance just creates an managed wrapper for a thread. Calling Start will set things in motion and eventually make your code run on a separate thread.
Probably you haven't started the thread, so its not running yet.
However, in your case its usually better to use BackgroundWorker class, this will create the thread for you and provide thread-safe way to update the UI with the progress of the threads work.