My code launches a background thread. The background thread makes changes and wants the UI in the main thread to update. The code that launches the thread then waits looks something like:
Thread fThread = new Thread(new ThreadStart(PerformSync));
fThread.IsBackground = true;
fThread.Start();
fThread.Join();
MessageBox.Show("Synchronization complete");
When the background wants to update the UI, it sets a StatusMessage and calls the code below:
static StatusMessage _statusMessage;
public delegate void AddStatusDelegate();
private void AddStatus()
{
AddStatusDelegate methodForUIThread = delegate
{
_statusMessageList.Add(_statusMessage);
};
this.Dispatcher.BeginInvoke(methodForUIThread, System.Windows.Threading.DispatcherPriority.Send);
}
_statusMessageList is an ObservableCollection that is the source for a ListBox.
The AddStatus method is called but the code on the main thread never executes - that is, _statusMessage is not added to _statusMessageList while the thread is executing. However, once it is complete (fThread.Join() returns), all the stacked up calls on the main thread are executed.
But, if I display a message box between the calls to fThread.Start() and fThread.Join(), then the status messages are updated properly.
What do I need to change so that the code in the main thread executes (UI updates) while waiting for the thread to terminate?
Thanks.
fThread.Join causes your main thread to block until the background thread finishes. As long as the main thread is blocked, the UI cannot be updated.
What you need to do is something like this (untested, but you should get the idea):
void someUiEventThatCausesTheBackgroundProcessingToStart() {
Thread fThread = new Thread(new ThreadStart(PerformSync));
fThread.IsBackground = true;
// disable some UI components here, so that the user cannot
// start the thread a second time
...
fThread.Start();
// *don't* call Thread.Join here, so that your main thread does not block!
}
void PerformSync() {
try {
// do your stuff here
...
} finally {
Dispatcher.Invoke(new Action(ProcessingDone));
}
}
void ProcessingDone() {
// re-enable the UI components
...
MessageBox.Show("Synchronization complete");
}
Of course, in WPF, disabling/enabling UI components is ideally done using some IsBusyProcessing dependency property which is bound with a trigger to the UI elements in question, but this is another story...
EDIT: As another option, you might want to check out the BackgroundWorker class, which contains ProgressChanged and RunWorkerCompleted events that automatically fire in the main thread.
fThread.IsBackground = true;
fThread.Start();
fThread.Join();
The call to Join() is blocking your main thread until the background thread finishes. So the UI thread can't do anything while the other thread is running. You need to not call Join(). If you need to do something on the main thread after the background thread finishes, find another way to do it.
EDIT: The reason it works if you display a message box between the call to Start and Join is because then the main thread is running the message loop for the message box, instead of being blocked at the Join call.
The BackgroundWorker is the right tool for this job. It's no more complicated than is absolutely necessary, gives you all of the hooks that you need for progress reporting, and there's plenty of information available (such as this answer) on how to use it.
Related
I am using SynchronizationContext as a means to synchronize to the GUI thread, for WinForms and WPF. Recently I ran into an issue with the old style async callbacks:
private void Button_Click(object sender, RoutedEventArgs e)
{
uiContext = SynchronizationContext.Current;
var cl = new TcpClient();
cl.BeginConnect("127.0.0.1", 22222, ConnectedCallback, null);
}
public void ConnectedCallback(IAsyncResult result)
{
if (SynchronizationContext.Current != uiContext)
uiContext.Post(x => MyUIOperation(), null);
else
MyUIOperation();
}
public void MyUIOperation()
{
Title = "Connected";
}
private SynchronizationContext uiContext;
This will throw an exception, because the SynchronizationContext.Current in the callback function is equal to the captured one, and therefore the UI operation is executed in the worker thread of the callback.
Using this exact same code in WinForms works as I had expected.
For now as a workaround, I am capturing the current ManagedThreadId instead and compare it in the callback. What is correct way to handle this?
Update:
I should add that I am modifying a very old existing class that currently uses the following construct:
if (control.InvokeRequired())
control.BeginInvoke(SomeFunction);
else
SomeFunction();
I am trying to remove the WinForms dependency, without having much impact on the clients of this class. The SomeFunction() is raising events, so if I just call uiContext.Send() or uiContext.Post() , the order of execution is changed since Post() will always queue the call, and Send() will always block.
Also, this is just a very small piece of code to show the root of my issue. In reality the function doing the Post() can be called from the main thread.
This is targeting .NET 4.0
It turned out, in .NET 4.5 the SynchronizationContext is in fact different in the callback function and the if statement would evaluate to true. This was a deliberate change, as discussed here
WPF 4.0 had a performance optimization where it would
frequently reuse the same instance of the
DispatcherSynchronizationContext when preparing the
ExecutionContext for invoking a DispatcherOperation. This
had observable impacts on behavior.
1) Some task-parallel implementations check the reference
equality of the SynchronizationContext to determine if the
completion can be inlined - a significant performance win.
2) But, the ExecutionContext would flow the
SynchronizationContext which could result in the same
instance of the DispatcherSynchronizationContext being the
current SynchronizationContext on two different threads.
The continuations would then be inlined, resulting in code
running on the wrong thread.
Because in my case, the call to MyUIOperation() function would need to
be called immediately if the ConnectedCallback function is called from
the main thread.
That means the call to MyUIOperation() would be a blocking call if the ConnectedCallback is invoked in the UI thread, as opposed to non-blocking if it is invoked from the another thread. This non-determinism could cause other problems down the road.
Just call Send instead. According to this article, the call to Send would just invoke the delegate directly if already in the UI thread.
Also, you could just do Dispatcher.Invoke() instead.
I'll try to be explicit. I create a Qt application, that has some buttons and a QTextEdit. Next i create a pthread. And offer the pointer to the MainWindow as the parameter. Something like this:
MainWindow w;
pthread_create(&rThread,NULL,treat,&w);
treat is the function that is executed when the thread is created. Now if i have a pushButton called myButton, and i do somthing like this inside the treat function:
void *treat(void *arg)
{
MainWindow *win = (MainWindow*)arg;
win->ui->myButton->setEnabled(false);
close(pthread_self());
}
It will work fine , and the myButton in my application will disable. However if i do something like this:
void *treat(void *arg)
{
MainWindow *win = (MainWindow*arg;
win->ui->editText->setText("random string");
close(pthread_self());
}
My application will crash with the following error:
QObject: Cannot create children for a parent that is in a different
thread. (Parent is QTextDocument(0x23af2e0), parent's thread is
QThread(0x209a290), current thread is QThread(0x7f7eec000af0) The
program has unexpectedly finished.
As i understand the Ui is living in the main thread, and probably is not accesible in the thread that i created , despite the fact that i offered the pointer of the main window to this thread. But why does disabling of the button work? I am very confused. The reason why i dint use the QThread is because our teacher told me not do it. I have to use pthreads. How could i apply such a change from the pthread to the editText ?
How could i send a signal from a pthread to the other thread in wich the Ui is "living". Thanks in advance guys.
Generally speaking, it's an error to call any of QObject (or derived classes') methods from a thread other than object->thread() - unless they are designed and documented to be thread-safe. There are a few methods in Qt proper that are explicitly documented as being thread safe, for example QCoreApplication::postEvent.
The behavior you're facing is due to accessing QWidget methods from the non-gui thread. It's undefined behavior, so some methods may crash, some won't, but even if they don't it's still undefined behavior that you can't count on. It may depend on the phase of the Moon, for all we know.
The only safe thing to do from another thread is to post an event to the object. When you use QMetaMethod::invoke or QMetaObject::invokeMethod on an object in another thread, Qt will internally post a QMetaCallEvent to the object. Since posting events is thread-safe (can be done from other threads), it's OK to do use either of those invoke methods from other threads. QObject::event() reacts to such events by executing the proper method call.
So, the only thing you can do from the other thread is:
QMetaObject::invokeMethod(win->ui->editText, "setText", Q_ARG(QString, "random string"));
Alas, this is bad design, since you're exposing MainWindow's internal details (like the ui pointer) to outside. What you should do instead is have a setEditText slot on the window:
MainWindow : public QWidget {
...
public:
Q_SLOT void setEditText(const QString & str) {
ui->editText->setText(str);
}
...
};
Then, from the other thread, you do:
QMetaObject::invokeMethod(win, "setEditText", Q_ARG(QString, "random string"));
I fully agree with Marek R's recommendation not to use pthreads when you have QThread available.
First of all mixing libraries when it is not necessary is bad habit. Qt provides QThread and very handy QtConcurrent.
Secondly this is bad design. Create some QObject which will handle yours calculations in thread and will emit signal when it should pass result to UI (main thread). Then create connection and Qt will handle rest of the stuff make it thread safe (by default it will queue connection if signal is passed between threads).
Your code with Qt concurrent:
void *treat(SomeClass *arg) {
arg->doStuff();
}
QtConcurrent::run(treat, someObject);
I have a program (written in C, currently running on Mac OS X 10.8.4) that simulates a world and updates the world's state multiple times per second.
At startup this program creates a background thread which creates a simple GTK window and calls gtk_main.
After each time the world's state is updated (in the main thread), I would like the window to reflect that change. My first approach was to simply update the GTK widgets after the world was updated, but because that was in a different thread things broke quite messily.
Is there some sort of mechanism where the main thread can update some state on the graphics thread and then queue an event that prompts the graphics thread to redraw? I.e.
void draw() {
// This can only be called from the graphics thread.
gtk_label_set(GTK_LABEL(label1), "some state");
}
// This causes draw() to be called on the graphics thread.
gtk_please_redraw_this_thing_on_the_graphics_thread();
Is there any way to do this? Or any tutorials that cover it?
Turns out this is quite simple.
First create the function that will do the drawing (on the graphics thread):
gboolean draw_function(GtkWidget *w, GdkEventExpose *event) {
// Draw things.
return TRUE;
}
Then, during set up, connect the draw event of your widget to your draw function:
g_signal_connect(G_OBJECT(some_widget), "draw", G_CALLBACK(draw_function), NULL);
Finally, to force the widget to redraw from another thread you can call:
gtk_widget_queue_draw(some_widget);
My label text isn't updating properly in my 3.5 WPF MVVM app.
The do work part lasts long enough that you can see the waiting mouse pointer.
All I ever see is "Parsed" in the label, which is Bound to InfoText.
the Dispatcher and do work lines are in a Command's method.
Ideas?
The code
Dispatcher.Invoke((Action<string>)SetInfoText, "Start Parsing");
//do work
Dispatcher.Invoke((Action<string>)SetInfoText, "Parsed");
private void SetInfoText(string text)
{
InfoText = text;
}
private string _infoText;
public string InfoText
{
get
{
return _infoText;
}
set
{
_infoText = value;
OnPropertyChanged("InfoText");
}
}
The only thing I can think of to explain it is that you're doing the work on the UI thread. This would prevent the dispatcher from redrawing until your work is done. The work being passed in Invoke is placed in the event queue, meaning it will be performed when idle.
The proper way to fix it is to do the work on a separate thread. If you're looking for workarounds though, look here.
Reference: MSDN
EDIT:
There are lots of ways to perform the work on another thread. Read up on BackgroundWorker, ThreadPool, Task Parallell Library, Threads. :)
Here's a really simple way to do the work in a background thread:
System.Threading.ThreadPool.QueueUserWorkItem( state =>
{
Dispatcher.Invoke((Action<string>)SetInfoText, "Start Parsing");
System.Threading.Thread.Sleep(5000); // Simulate work
Dispatcher.Invoke((Action<string>)SetInfoText, "Parsed");
});
Application.Current.Dispatcher.BeginInvoke(new Action(() => this.InfoText="Start Parsing"));
this works for me.
nevertheless i would put my long running process in a backgroundworker. so ui thread will not get blocked.
edit: if you do all your work in ui thread you should look at the overload for BeginInvoke - you can pass a DispatcherPriority. may be this helps too
With reference to this programming game I am currently building.
I have a Class Library (dll) that will have a method Run which will be composed of something like such:
public class MyRobot : Robot
{
public void Run(}
{
while (true)
{
Ahead(200); //moves the bot 200pixels
TurnLeft(90); //turns the bot by 90deg
}
}
}
In those methods (inherited from Robot), the system will animate the robot using WPF (using BeginAnimation or the DispatcherTimer).
Now, the problem is that I don't a method to return (ie, move on to the next method) before completing the current one, because that will result in the animations taking place together, and when in an infinite loop (like the one above), that's especially not good.
My question is, what is the best way to prevent a method from returning before completing the animation ?
I currently have a bool in the Robot class (isActionRunning) that be flagged to true when an action starts running and then changes to false in an animation callback (using the Completed event if using BeginAnimation).
At the end of each method (after invoking BeginAnimation) I placed the following loop :
while (isActionRunning)
{
Thread.Sleep(200); //so that the thread sleeps for 200ms and then checks again if the animation is still running
}
This is so that the method won't return before the animation finishes.
But I feel that this is not the right way to do this.
Can anyone guide me to what's best to achieve this ?
Building a signalling device out of locks is craziness; just use the signalling device that already exists in the framework.
http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
That is: thread one says "hey thread two, start this animation and signal me on this wait handle when you're done." Thread one then waits on the waithandle. Thread two starts the animation, and in its completion event, signals the waithandle. Thread one then wakes up again and says "hey thread two, start this other animation..."
Here's one option, it will only work if the Robot.Run code is running in a different thread than the UI thread doing the animations.
In the Robot.Ahead method (for example), use Dispatcher.Invoke (not BeginInvoke) to call the method that starts the animation, than add a lock on the robot with an empty block( lock(this) { } ).
In the method that starts the animation call Monitor.Enter(robot) before starting the animation
In the animation complete handler call Monitor.Leave(robot)
The result will be
time robot thread UI thread
| --------------- --------------
| call Invoke --->
| lock robot (Monitor.Enter)
| begin animation
| Invoke returns <--- return
| lock(this) (animation running)
| (wait for lock
| to become available)
|
| Animation complete
| release lock (Monitor.Exit)
| (lock available,
| continue running)
| Release lock (exit lock block)
| Return and start next
| movement
\/
I would do something similar to what you described. I recently worked on something where I called a bunch of asynchronous operations, and I wanted to wait for them all to complete before calling another operation. I created a collection to represent all of the operations currently executing and instead of adding items to the collection directly, I created methods for adding and removing. The remove method had logic that said "lock the collection, remove the key provided, and if empty call the next operation". You could create a similar mechanism like this where a collection scoped at the application or window keeps track of operations being executed. You add a key to the collection and pass this key to your async operation. When the async operation completes, lock the collection and remove the key. Then you can have a loop that blocks your method from returning while the collection contains the key (with optional logic for adding a timeout or any other additional ways where you might want the method to be able to return and not be blocked forever).
This might be overkill, but I have limited experience with this issue myself. For all I know, .Net might even have a canned solution to this problem that works with one or two lines of code.