Delegates and thread: CallbackContext parameter - c++

I'm implementing threading in Metro mode, I got this example while Googling, but I don't understand CallbackContext . What's the use of this? This explains its use in MTA, but not clear to me. And I'm facing problem when I use CallbackContext as Any or Same. Something work with one but not with other! So first thing first I want to know what's the use of this?! PS: I'm new to WindowsRT programming and C++ too! Thanks!
auto workItemHandler = ref new WorkItemHandler([=](IAsyncAction^)
{
// Run the user callback.
try
{
func(data);
}
catch (...)
{
}
// Signal that the thread has completed.
SetEvent(completionEvent);
//CloseHandle(completionEvent);
}, CallbackContext::Same);

CallbackContext determines whether your delegate (in this case, a WorkItemHandler) aggregates the free-threaded marshaller. This will determine whether your delegate can be smuggled to another apartment (CallbackContext::Any), or if it must be called back to the originating apartment (CallbackContext::Same). Basically, it tells the person invoking your delegate whether it can be called directly regardless of apartment, or if they need to marshal back to the apartment it was created in.
For example, in a Windows Store Application, anything that modifies the UI needs to run on the UI thread (STA). Let's presume the method you're in is one that runs on the UI thread (such as an event callback, like a button click handler). Certain async calls like ThreadPool::RunAsync will run the passed-in delegate on a thread other than the UI thread (as the default for delegates is CallbackContext::Any). This is useful if you do not need to do anything on the UI thread, as it frees that thread up to continue pumping messages (and your app continues to feel performant).
However, if you do need to modify the UI or make a call back into the UI, and you attempt to do so from a non-UI thread, you will get an incorrect thread exception. By adding the parameter CallbackContext::Same you can force your delegate to run in the originating apartment (in this scenario, the STA) and thereby avoid the issue.
(You can also make a call back to the UI thread by using Dispatcher->RunAsync to invoke a further delegate to run on the STA. Whether it's better for your entire delegate to run on the STA or not depends on your scenario.)

Related

Qt : qt cannot send events to objects owned by a different thread - Why

I am developing an application with Qt whereby I want to update my GUI from another unrelated class with functions executing in a different thread.
I registered a callback function from the Qt GUI class to the other class using standard C++ constructs std::function and std::bind.
On trying to execute the GUI callback function from the other class, my program crashes with "qt cannot send events to objects owned by a different thread".
My questions are, what is happening here exactly. Why is it not permissive to communicate between two threads like this. Is it possible to resolve this in some way , or does Qt just not allow other unrelated functions to update the GUI in this way ?
For information , I am using portaudio libraries on windows. It executes a callback in a different thread. When I receive audio, I try to update my GUI.
Thank you in advance
You're probably being thrown off by the "send events" phrase. In Qt, this phrase has a strict technical meaning. Namely:
to send events means to use QCoreApplication::sendEvent, which then immediately invokes QObject::event on the receiver. It is an error to send events when the sending and receiving threads are different.
to post events means to use QCoreApplication::postEvent, which posts the event to the receiving object thread's event queue. The QObject::event on the receiver is invoked later by the receiver thread's event loop.
When objects live in different threads, you're not allowed to send events, only to post them. This points to the underlying cause of your issue/
Any method you access on a QWidget or a derived class must be accessed on its thread(), i.e. the main thread. Everything inside of QWidget can use sendEvent freely as the sending thread and receiving object's thread are identical by contract. By calling QWidget methods from the wrong thread, you break that contract by indirectly using sendEvent and thus fail.
Only methods that you yourself have implemented and are thread-safe can be called from other threads - and they can't use sendEvent.

Emitting a Qt::signal from worker thread makes the UI update on main thread by default?

I am new to Qt. I have worker thread that is an std::thread. The worker thread function continuously fetches some some data in a loop. The size of the data is frequently updated on a Text element on a QML UI. I have a listener callback which is nothing but an std::function and it gets called from the thread's function. It sends me callbacks based on which I updated the Text element on QML. I update it using signal slot mechanism.
Following is the QML : Text element:
Text {
id: mytext
objectName: "mytextobject"
function slotUpdateData(someValue){
mytext = someValue
}
}
SignalUpdateData is connected with slotUpdateData which resides on QML side. Every time I get the data event callback from the std::thread, I emit SignalUpdateData which updates the QML Text element on UI.
void CallBackReceivedFromWorkerThread(float someValue) {
emit SignalUpdateData(someValue)
}
Following is how I have connected this C++ signal with the QML slot
QObject::connect(this, SIGNAL(SignalUpdateData(QVariant)), myTextItemQObject, SLOT(slotUpdateData(QVariant)));
And all of this works fine. No crashes, lock-ups, nothing.
As per my understanding, since the worker thread's function is triggering the callback, the execution control is on the worker thread when the callback is received. So when doing emit SignalUpdateData(someValue), we'er still on the worker thread. And as far as I know from my previous experience in android & java, we cannot update the UI from anywhere outside the main thread of the application.
So, How is this working ? Is emit SignalUpdateData(someValue) putting the call into the main UI thread's event loop ? Is Qt still making the UI change on main thread in spite of me calling for it from a worker thread ? If my approach is fine, then does it have performance implications ? What is the best recommendation to do this ?
I want to be very sure about this & not just lucky about making this to work. Should I use a Qt::Connection_enum as well for best approach ?
You're leveraging Qt the way it was meant to be! And you've run into it accidentally: that's a sign of a decent design - it "just works". Hooray for you, hooray for Qt :)
It's working because Qt has been designed specifically to make it work, and you're using the default automatic connection whose raison d'ĂȘtre is to help you out in this specific case. So you happen to be doing everything right: change nothing!
When you emit a signal, Qt acquires relevant source and destination object mutexes, and compares the receiving object's thread() to QThread::currentThread(). If they are identical, the slot/functor is called immediately: it happens in the body of the signal, so the slot is called before the signal returns. This is safe as the target object is used from its thread(), where it's safe.
If target->thread() != QThread::currentThread(), then a QMetaCallEvent is queued to the target object. The event contains the (equivalent of) slot method pointer and a copy of any parameters passed by the slot. The QObject::event implementation handles the event and executes the call. The target object thread's event loop is on the call stack, since its job is to deliver the queued events to the object.
The above is, in a nutshell the meaning of a Qt::AutoConnection. If you're using Qt::QueuedConnection, the 2nd case applies no matter what the threads are. If you're using Qt::DirectConnection, the 1st case applies no matter what.
My guess is that >95% of the uses of a non-automatic connection type in Qt-related questions on SO are unnecessary and stem from lack of understanding and resorting to what amounts to magic incantations.

Can I have multiple GUI threads in MFC?

I have a large MFC based application that includes some potentially very slow tasks in the main thread. This can give the appearance that the application has hung when it is actually working its way through a long task. From a usability point of view, I'd like to be giving the user some more feedback on progress, and have an option to abort the task in a clean manner. While hiving the long tasks off into separate threads would be a better long term solution, I'm thinking a pragmatic short term solution is create a new GUI thread encapsulated in its own object complete with dialog including progress bar and cancel button, used in a similar manner to a CWait object. The main thread monitors the cancel status via an IsCancelled method, and finishes via a throw when required.
Is this a reasonable approach, and if so is there some MFC code out there already that I can use, or should I roll my own? First sketch looks like this
class CProgressThread : public CWinThread
{
public:
CProgressThread(int ProgressMax);
~CProgressThread()
void SetProgress(int Progress);
BOOL IsCancelled();
private:
CProgressDialog *theDialog;
}
void MySlowTask()
{
CProgressThread PT(MaxProgress);
try
{
{
{ // deep in the depths of my slow task
PT.SetProgress(Progress);
if (PT.IsCancelled())
throw new CUserHasHadEnough;
}
}
}
catch (CUserHasHadEnough *pUserHasHadEnough)
{
// Clean-up
}
}
As a rule, I tend to have one GUI thread and many worker threads, but this approach could possibly save me a bunch of refactoring and testing. Any serious potential pitfalls?
Short answer, Yes, you can have multiple GUI thread in MFC. But you can't access the GUI component directly other than the created thread. The reason is because the Win32 under the MFC stores the GUI handler per thread based. It means the handler in one thread isn't visible to another thread. If you jump to the CWinThread class source code, you can find a handler map attribute there.
Windows (MFC) doesn't has hard difference between the worker thread & GUI thread. Any thread can be changed to GUI thread once they create the message queue, which is created after the first call related to the message, such as GetMessage().
In your above code, if the progress bar is created in one thread and MySlowWork() is called in another thread. You can only use the CProgressThread attributes without touch the Win32 GUI related functions, such as close, setText, SetProgress... since they all need the GUI handler. If you do call those function, the error will be can't find the specified window since that handler isn't in the thread handler mapping.
If you do need change the GUI, you need send the message to that progress bar owner thread. Let that thread handles the message by itself (message handler) through the PostThreadMessage, refer to MSDN for detail.

Callback with XPCOM

I would like to implement the observer pattern similar to Timer component. Instead of calling a callback by time expiration, the callbacks that are observers of a topic would be called from system events (like new file created, or a new e-mail received, etc.). I tried using nsIObserverService in the component XPCOM, but it seems that functions from component aren't able to call observers in JavaScript by using NotifyObservers. The NotifyObservers only works when is called from JavaScript.
Thanks in advance
Example::Example always runs on the main thread (because it's being created by your script). So it never creates a proxy to the observer service. But the call to Example::Call from Ex::Run happens on the background thread, and I think in this case the call to NotifyObservers returns NS_ERROR_UNEXPECTED (which you ignore).

When to use QThread::exec()

I've checked a satisfying explanation but could not find. Usually docs mention that in order to use signals/slots between threads, we need to use event loops and start them by calling exec.
However I can see that w/o using exec(), I can still send signals and handle them across threads.
What's the exact use of it?
Use QThread::exec() when you want to run the event loop Qt provides for you in the QThread class. If you don't call exec(), you need to create your own event loop that processes Qt events (that is, if you want signals / slots to work). This is almost certainly more work than it's worth, unless you have very specific needs.
You say you can still send signals / slots? My guess is that you're not actually running anything on a different thread. This is a very common issue when using QThread. Put a breakpoint inside the code you think is running on a different thread and have a look at the stack trace - you may be in for a shock!
A rough example.
Suppose you have a text box. On each letter user types on the text box you want to perform some background task. You can setup a QThread for that. Emit something whenever the contents of text box changes. Assign a slot from your QThread that handles the background task. Emit something from QThread when the task finished. Handle this signal from main thread. Connect them. Start the thread when the text box is created (or any appropriate time). If you call exec() from your QThread::run() then you don't need to start() the thread multiple times.
If you don't use this mechanism, you may need to create (and/or start()) a QThread each time the content of text box changes, perform the background task and get result. This time you can still use signal/slot between main thread and this thread, but you need to start() the thread multiple times.