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);
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.
Alright, I honestly have tried looking up "Asynchronous Functions in C" (Results are for C# exclusively), but I get nothing for C. So I'm going to ask it here, but if there are better, already asked questions on StackExchange or what-have-you, please direct me to them.
So I'm teaching myself about concurrency and asynchronous functions and all that, so I'm attempting to create my own thread pool. So far, I'm still in the planning phase of it, and I'm trying to find a clear path to travel on, however I don't want a hand-out of code, I just want a nudge in the right direction (or else the exercise is pointless).
What would be the best way to asynchronously return from a function that isn't really "ready"? In that, it will return almost immediately, even if it's currently processing the task given by the user. The "task" is going to be a callback and arguments to fit the necessary pthread_t arguments needed, although I'll work on attributes later. The function returns a struct called "Result", which contains the void * return value and a byte (unsigned char) called "ready" which will hold values 0 and 1. So while "Result" is not "ready", then the user shouldn't attempt to process the item yet. Then again, the "item" can be NULL if the user returns NULL, but "ready" lets the user know it finished.
struct Result {
/// Determines whether or not it has been processed.
unsigned char ready;
/// The return type, NULL until ready.
void *item;
};
The struct isn't really complete, but it's a basic prototype embodying what I'm attempting to do. This isn't really the issue here though, although let me know if its the wrong approach.
Next I have to actually process the thing, while not blocking until everything is finished. As I said, the function will create the Result, then asynchronously process it and return immediately (by returning this result). The problem is asynchronously processing. I was thinking of spawning another thread inside of the thread_pool, but I feel it's missing the point of a thread pool as it's not longer remaining simple.
Here's what I was thinking (which I've a feeling is grossly over-complicated). In the function add_task, spawn a new thread (Thread A) with a passed sub_process struct then return the non-processed but initialized result. In the spawned thread, it will also spawn another thread (see the problem? This is Thread B) with the original callback and arguments, join Thread A with Thread B to capture it's return value, which is then stored in the result's item member. Since the result will be pointing to the very same struct the user holds, it shouldn't be a problem.
My problem is that it spawns 2 threads instead of being able to do it in 1, so I'm wondering if I'm doing this wrong and complicating things.Is there a better way to do this? Does pthread's library have a function which will asynchronously does this for me? Anyway, the prototype Sub_Process struct is below.
/// Makes it easier than having to retype everything.
typedef void *(*thread_callback)(void *args);
struct Sub_Process {
/// Result to be processed.
Result *result;
/// Thread callback to be processed
thread_callback cb;
/// Arguments to be passed to the callback
void *args;
};
Am I doing it wrong? I've a feeling I'm missing the whole point of a Thread_Pool. Another question is, is there a way to spawn a thread that is created, but waiting and not doing anything? I was thinking of handling this by creating all of the threads by having them just wait in a processing function until called, but I've a feeling this is the wrong way to go about this.
To further elaborate, I'll also post some pseudocode of what I'm attempting here
Notes: Was recommended I post this question here for an answer, so it's been copy and pasted, lemme know if there is any faulty editing.
Edit: No longer spawns another thread, instead calls callback directly, so the extra overhead of another thread shouldn't be a problem.
I presume it is your intention is that a thread will request the asychronous work to be performed, then go on to perform some different work itself until the point where it requires the result of the asynchronous operation in order to proceed.
In this case, you need a way for the requesting thread to stop and wait for the Result to be ready. You can do this by embedding a mutex and condition variable pair inside the Result:
struct Result {
/// Lock to protect contents of `Result`
pthread_mutex_t lock;
/// Condition variable to signal result being ready
pthread_cond_t cond;
/// Determines whether or not it has been processed.
unsigned char ready;
/// The return type, NULL until ready.
void *item;
};
When the requesting thread reaches the point that it requires the asynchronous result, it uses the condition variable:
pthread_mutex_lock(&result->lock);
while (!result->ready)
pthread_cond_wait(&result->cond, &result->lock);
pthread_mutex_unlock(&result->lock);
You can wrap this inside a function that waits for the result to be available, destroys the mutex and condition variable, frees the Result structure and returns the return value.
The corresponding code in the thread pool thread when the processing is finished would be:
pthread_mutex_lock(&result->lock);
result->item = item;
result->ready = 1;
pthread_cond_signal(&result->cond);
pthread_mutex_unlock(&result->lock);
Another question is, is there a way to spawn a thread that is created,
but waiting and not doing anything? I was thinking of handling this by
creating all of the threads by having them just wait in a processing
function until called, but I've a feeling this is the wrong way to go
about this.
No, you're on the right track here. The mechanism to have the thread pool threads wait around for some work to be available is the same as the above - condition variables.
I have the example GTK C application from [1] building and working as expected. I have a pretty little UI application with a + and - button to increment/decrement a value stored in a global variable, and render it in the application in a text label.
I rarely ever work with GUI applications, and I do 99% of my work in C. I have two key questions with respect to tidying up this example and using it as the basis of a project.
Is it possible to have some alternative to global variables, like a
custom struct I create in main(), and have every callback handler reference
it by changing the function protocol for increase()?
Code:
// Can this function protocol be modified?
void increase(GtkWidget *widget, gpointer label) {
count++;
sprintf(buf, "%d", count);
gtk_label_set_text(GTK_LABEL(label), buf);
}
g_signal_connect(minus, "clicked", G_CALLBACK(decrease), label);
Is there a simple means of creating a separate thread to help manage the GUI? For example, if I have a button tied/connected to a function that would take a minute to complete, is there a universally-accepted means of firing off a separate pthread that allows me to have a button or command to cancel the operation, rather than the entire UI app being blocked for the whole minute?
Thank you.
References
Cross Compiling GTK applications For the Raspberry Pi, Accessed 2014-02-20, <http://hertaville.com/2013/07/19/cross-compiling-gtk-applications-for-the-raspberry-pi/>
Yes, you can pass anything you like as the last argument to signal handlers (gpointer is a typedef for void*) just create the structure containing the label widget and the counter variable in main(), pass it as the last argument to g_signal_connect and cast it back to the proper type in your callback.
For running a calculation in another thread and delivering the result to the gtk main loop I'd look at GTask, in particular g_task_run_in_thread_async.
I'm trying to use mmTimer with a callback function, which is a static CALLBACK function.
I know that a static function cannot call a non-static function, thanks to you all guys, except from the case where the static function gets a pointer to an object as an argument.
the weird thing is that my timer works fine in release mode, and when I try to run it in debug mode there is this unhandeled exception that pops up and breaks the program down.
void CMMTimerDlg::TimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
CMMTimerDlg* p = (CMMTimerDlg*)dwUser;
if(p)
{
p->m_MMTimer += p->m_TimeDelay;
p->UpdateData(FALSE);
}
}
my questions are : - is there any way to resolve this problem? - If this error occurs on debug mode, who ensures me that it wouldn't happen once i release the program?
there is where the program stops:
#ifdef _DEBUG
void CWnd::AssertValid() const
{
if (m_hWnd == NULL)
return; // null (unattached) windows are valid
// check for special wnd??? values
ASSERT(HWND_TOP == NULL); // same as desktop
if (m_hWnd == HWND_BOTTOM)
ASSERT(this == &CWnd::wndBottom);
else if (m_hWnd == HWND_TOPMOST)
ASSERT(this == &CWnd::wndTopMost);
else if (m_hWnd == HWND_NOTOPMOST)
ASSERT(this == &CWnd::wndNoTopMost);
else
{
// should be a normal window
ASSERT(::IsWindow(m_hWnd));
// should also be in the permanent or temporary handle map
CHandleMap* pMap = afxMapHWND();
ASSERT(pMap != NULL);
when it gets to pMap it stops at that assertion!!!!
here is the static CALLBACK function
static void CALLBACK TimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2);
here is how I set the timer
UINT unTimerID = timeSetEvent(m_TimeDelay,1,(LPTIMECALLBACK)TimerProc,(DWORD)this,TIME_PERIODIC);
The problem here is that multimedia timer API unlike many other has restrictions on what you are allowed to do inside the callback. You are basically not allowed much and what you are allowed is to update internal structures, do some debug output, and set an synchronization event.
Remarks
Applications should not call any system-defined functions from inside
a callback function, except for PostMessage, timeGetSystemTime,
timeGetTime, timeSetEvent, timeKillEvent, midiOutShortMsg,
midiOutLongMsg, and OutputDebugString.
Assertion failures start display message boxes which are not allowed and can eventually crash the process. Additionally, windowing API such as IsWindow and friends are not allowed either and are the first place cause leading further to assertion failures.
The best here is to avoid using multimedia timers at all. In most cases you have less restrictive alternate options.
It only looks like your code works in the Release build, it will not assert() that you are doing it right. And you are not doing it right.
The callback from a multi-media timer runs on an arbitrary thread-pool thread. You have to be very careful about what you do in the callback. For one, you cannot directly touch the UI, that code is fundamentally thread-unsafe. So you most certainly cannot call UpdateData(). At best, you update a variable and let the UI thread know that it needs to refresh the window. Use PostMessage(). In general you need a critical section to ensure that your callback doesn't update that variable while the UI thread is using it to update the window.
The assert you get in the Debug build suggests more trouble. Looks like you are not making sure that the timer can no longer callback when the user closes the window. That's pretty hard to solve cleanly, it is a fundamental threading race. PostMessage() will already keep you out of the worst trouble. To do it perfectly clean, you must prevent the window from closing until you know that the timer cannot callback anymore. Which requires setting an event when you get WM_CLOSE and not call DestroyWindow. The timer's callback needs to check that event, call timeKillEvent() and post another message. Which the UI thread can now use to really close the window.
Threading is hard, do make sure that SetTimer() isn't already good enough to get the job done. It certainly will be if the UI update is the only side-effect. You only need timeSetEvent() when you require an accurate timer that needs to do something that is not UI related. Human eyes just don't have that requirement. Only our ears do.
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.