If an object of type QObject is moved to a thread with QObject::moveToThread, all signals that the object receives are handled inside that thread. However, if a slot is called directly (object->theSlot()) that call will still block. What would be the normal way of executing that call inside the thread and returning control to the calling thread immediately? Hacks with QTimer don't count. Setting up a single purpose connection and deleting it again might count as a solution if all else fails.
You could use QMetaObject::invokeMethod with Qt::ConnectionType set to Qt::QueuedConnection
You can use QFuture<T> QtConcurrent::run ( Function function, ... ) to launch some execution inside a separate thread and then use QFutureWatcher to get the result. You will not need to call movetoThread.
Basically something like :
QFutureWatcher<T>* watch = new QFuture(0);
connect(watch, SIGNAL(finished()), this, SLOT(handleResult()));
QFuture<T> future = QtConcurrent::run( myObj, &QMyObject::theSlot(), args...);
watch.setFuture(future);
....
//slot
private void handleResult(){
if(future->isCancelled())
return;
T mydata = watch->future()->result();
// use your data as you want
}
QtConcurrent::run will schedule the method of this object to be ran in some thread. It is non-blocking. On the other hand, QFuture::result() blocks until there is a result, if the computation is still ongoing. That's why you need the other object to notify when the computation is over using finished(). I cannot think of a better design for your problem in Qt.
Related
I would like someone to explain to me what is Device.BeginInvokeOnMainThread and what is it for?
And also some examples of cases where it's used.
Just to add an example.
Imagine you have an async method DoAnyWorkAsync if you call it (just as an example) this way:
DoAnyWorkAsync().ContinueWith ((arg) => {
StatusLabel.Text = "Async operation completed...";
});
StatusLabel is a label you have in the XAML.
The code above will not show the message in the label once the async operation had finished, because the callback is in another thread different than the UI thread and because of that it cannot modify the UI.
If the same code you update it a bit, just enclosing the StatusLabel text update within Device.BeginInvokeOnMainThread like this:
DoAnyWorkAsync().ContinueWith ((arg) => {
Device.BeginInvokeOnMainThread (() => {
StatusLabel.Text = "Async operation completed...";
});
});
there will not be any problem.
Try it yourself, replacing DoAnyWorkAsync() with Task.Delay(2000).
The simple answer is: Background thread cannot modify UI elements because most UI operations in iOS and Android are not thread-safe; therefore, you need to invoke UI thread to execute the code that modifies UI such MyLabel.Text="New Text".
The detailed answer can be found in Xamarin document:
For iOS:
IOSPlatformServices.BeginInvokeOnMainThread() Method simply calls NSRunLoop.Main.BeginInvokeOnMainThread
public void BeginInvokeOnMainThread(Action action)
{
NSRunLoop.Main.BeginInvokeOnMainThread(action.Invoke);
}
https://developer.xamarin.com/api/member/Foundation.NSObject.BeginInvokeOnMainThread/p/ObjCRuntime.Selector/Foundation.NSObject/
You use this method from a thread to invoke the code in the specified object that is exposed with the specified selector in the UI thread. This is required for most operations that affect UIKit or AppKit as neither one of those APIs is thread safe.
The code is executed when the main thread goes back to its main loop for processing events.
For Android:
Many People think on Xamarin.Android BeginInvokeOnMainThread() method use Activity.runOnUiThread(), BUT this is NOT the case, and there is a difference between using runOnUiThread() and Handler.Post():
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);//<-- post message delays action until UI thread is scheduled to handle messages
} else {
action.run();//<--action is executed immediately if current running thread is UI thread.
}
}
The actual implementation of Xamarin.Android BeginInvokeOnMainThread() method can be found in AndroidPlatformServices.cs class
public void BeginInvokeOnMainThread(Action action)
{
if (s_handler == null || s_handler.Looper != Looper.MainLooper)
{
s_handler = new Handler(Looper.MainLooper);
}
s_handler.Post(action);
}
https://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable)
As you can see, you action code is not executed immediately by Handler.Post(action). It is added to the Looper's message queue, and is handled when the UI thread's scheduled to handle its message.
You can only update the UI from the main UI thread. If you are running code on a background thread and need to update the UI, BeginInvokeOnMainThread() allows you to force your code to run on the main thread, so you can update the UI.
As explained above, any UI updates must happen in the main thread or an exception will occur.
Though there's a peculiarity with Xamarin.Forms, one can manilpulate UI elements (e.g. create Labels and add them to StackLayout's Children collection) off the main thread without any failures as long as this part of UI is detached from UI elements currently displayed. This approach can be used to boost performance by creating Xamarin.Forms controls and setting their child/parent relations in-memory/off-screen in a separate thread BUT in order to attach them to displayed container (e.g. assign ContentPage's Content property) you will have to do this in Device.BeginInvokeOnMainThread().
While analysing the relationship between UI thread and background thread in some situation, we should be aware of the following:
BeginInvokeOnMainThread method as described in the docs, merely queues the invocation and returns immediately to the caller. So in this case, UI thread and background thread which submitted some work to UI thread, might work in parallel.
However, there is also InvokeOnMainThread which, as described in the docs, waits for the UI thread to execute the method, and does not return until the code pointed by action has completed. So in this case, background thread waits for UI thread to finish executing the given work, and then background thread continues execution.
Have a simple Qt app. Gui thread, creates Dev thread it creates (in its run()) Read thread. Dev and Read threads are my classes inherited from QThread. The Read thread should read data from COM port continuously. An approximate view of Read run is following.
read::run()
{
sp2->clear();
while (DO_EXEC)
{
if (DO_WRITE)
{
// write data to port
}
usleep(500);
ba = sp2->bytesAvailable();
if (ba > 0)
{
int a = sp2->read(&BUF[BUF_END], ba);
// process data
emit sgnl(sendeddata);
}
}
}
To start it I emit signal in GUI that is passed to Dev at it is passed to the following read slot:
read::slot_readStart()
{
// some stuff
if (doStart && !isRunning())
{
sp2 = new QSerialPort(this);
sp2->setPortName("COM3");
sp2->setBaudRate(256000);
sp2->setDataBits(QSerialPort::Data8);
sp2->setStopBits(QSerialPort::OneStop);
sp2->setParity(QSerialPort::NoParity);
sp2->setFlowControl(QSerialPort::NoFlowControl);
sp2->setReadBufferSize(5000);
bool isOpen = sp2->open(QIODevice::ReadWrite);
DO_EXEC = true;
start();
}
}
This works. But, if I place creating and setup and opening serial port to run method, then the port is open, but the bytesAvailable() are always zero? Why it is possible?
Thank you in adcance.
I agree with Orest Hera, in that you are using a "non recommended" way of implementing threads.
You are using inheritance for your thread object.
It is important to understand how QThreads work. The general procedure to using the QThreads is:
Make Object to go into thread, assign no parent
Make thread
Move object into thead using obj->moveToThread(thread)
Connect a signal to a slot in the object that will instatiate the object members (if required)
Start the thread: thread->start()
For example:
MyObj *myObj = new MyObj(0); // 0 = no parent if your object inherits QObject
QThread* thread = new QThread;
myObj->moveToThread(thread);
QObject::connect(thread, SIGNAL(started()), myObj, SLOT(run()));
thread->start();
So your object can still have its "run()" function, but it won't be overloading anything.
Also your run() function does not need to be a "forever" loop, it is simply an initialization function (create the serial port or whatever). Then you add other slots for other events, e.g. you can connect the QSerialPort::readyRead() to your "incoming data slot" handler to handle any data received from the serial port.... and so on.
I think this will solve your issues. It is difficult to tell exactly why your serial port does not work in your overloaded "Run()" function because I can't see how you are calling /creating the thread (i.e. the rest of your code) or where DO_EXEC is initialized etc... There is probably some ordering of events or thread ownership issue here.
Note: I am not saying you can't inherit thread class, but if you do that it is so that you create your own custom thread class (to do thread stuff), but not some other class to create a hybrid of thread utility and other stuff. There is a fair amount of information relating to this here (on SO) and on the qt forum if you are interested in the why/how etc... :)
I need to update a QGraphicsView with a QGraphicsScene from a thread.
Below is some pseudo'ish code example of what I am doing which is causing me issues (runtime errors).
What am I doing wrong, and how should I be doing it?
Main App:
void Main::startThread()
{
view = new QGraphicsView(...);
thread = new MyThread(...);
connect(thread, SIGNAL(doSceneUpdate(QGraphicsScene*)), this, SLOT(updateScene(QGraphicsScene*)));
thread->start();
}
void Main::updateScene(QGraphicsScene *scene)
{
view->SetScene(scene);
view->show();
repaint();
}
The Thread:
void MyThread::run()
{
QGraphicsScene *scene = new QGraphicsScene(...);
while(1)
{
//draw stuff on the scene
emit doSceneUpdate(scene);
//some delay
}
Thanks in advance!!!
[edit]
The error is:
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread
3e53c0. Receiver '' (of type 'QGraphicsScene') was created in thread 1476cd18", file c:\Qt\qt-everywhere-opensource-src-4.8.2\src\corelib\kernel\qcoreapplication.cpp, line 501
What am I doing wrong, and how should I be doing it?
I think the canonical answer is here -- in a nutshell, the article states that you shouldn't be subclassing QThread, but rather you should use a "bare" (i.e. not-subclassed) QThread object and connect its started() signal to a slot that will then be run in the context of that thread, after the thread starts. That way the object-thread-ownership issues are handled automatically for you.
Note also that threads other than the main Qt thread are generally not allowed to create or interact directly with GUI objects like QGraphicsScene, since doing that would introduce race conditions due to the operations going on simultaneously behind the scenes in Qt's GUI event loop. If you want to use a separate thread, you'll need to keep it away from your GUI objects, and instead just have it emit asynchronous signals and/or send Events to the main/GUI thread to get the main/GUI thread to do the GUI-object updates on its behalf.
The problem is with your connection line. You are connecting a slot to a signal which does not make sense. You should connect the signal from the thread to the slot :
connect(thread, SIGNAL(doSceneUpdate(QGraphicsScene*)),this, SLOT(updateScene(QGraphicsScene*)));
in
void MyThread::run()
{
QGraphicsScene *scene = new QGraphicsScene(...);
...
}
do you pass this to the constructor of QGraphicsScene()?
That could be one cause of error, since now you are passing a child of MyThread to Main
Try creating a QGraphicsScene object on the stack or with the parent as NULL ( new QGraphicsScene(0) )
Wiki Link for SDL_AddTimer
The wiki document for SDL_AddTimer claims that
"Note that it is possible to avoid the multithreading problems with SDL timers by giving to userevent.data1 the address of a function you want to be executed and to userevent.data2 its params, and then deal with it in the event loop."
How it is used to avoid multithreading problem?.
Can someone explain what is it i am unable to understand the statement ?
The first example assumes the working function, i.e. the function you want to execute ( my_function() ), resides in the my_callbackfunc() function.
SDL_AddTimer() specifies: Use this function to set up a callback function to be run on a separate thread after the specified number of milliseconds has elapsed.
This will introduce concurrency problems with my_function().
The solution (second example), assumes the event polling thread is the same thread that added the timer, and calls the function in that thread.
I've read that SDL documentation as well, and it makes a really bad suggestion for its "workaround". Specifically, it recommends casting a function address to a void pointer. This is not portable! Do not do it and please read
https://isocpp.org/wiki/faq/pointers-to-members#cant-cvt-fnptr-to-voidptr
If you feel that you must do this (or something like it) then I'd suggest wrapping the function pointer inside a struct/class.
struct Wrapper
{
void (*f)(void*);
Wrapper(void (*F)(void*)) { f = F; }
};
Create the wrapper when you want to push the custom event
SDL_Event event;
event.user.data1 = (void*) new Wrapper(your_function);
event.user.data2 = your_function_arg;
SDL_PushEvent(&user);
Then in your main loop, do the call, delete the wrapper
SDL_WaitEvent(&event);
if (event.type == SDL_USEREVENT)
{
Wrapper *p = ((Wrapper*) event.user.data1)
p->f(event.user.data2);
delete p;
}
I can't seem to find a .NET answer to this problem, which I would have thought would be fairly common.
What is the best pattern for unit testing an asynchronous method?
Obviously I need to call the method and then see if the callback fires, but is there a better way than simply sleeping for a bit and then checking for a flag that is set by the callback? Managing the flags gets a bit messy where there are multiple tests running.
I typically use an anonymous delegate and a waithandle. FOr example I have a function in my presenter called SetRemoteTableName. When the name is set, it also raises an event. I want to test that event, which is raised asynchronously. The test looks like this:
[TestMethod]
[WorkItem(244)]
[Description("Ensures calling SetRemoteTableName with a valid name works
AND raises the RemoteTableNameChange event")]
public void SetRemoteTableNamePositive()
{
string expected = "TestRemoteTableName";
string actual = string.Empty;
AutoResetEvent are = new AutoResetEvent(false);
SQLCECollectorPresenter presenter = new SQLCECollectorPresenter();
presenter.RemoteTableNameChange += new EventHandler<GenericEventArg<string>>(
delegate(object o, GenericEventArg<string> a)
{
actual = a.Value;
are.Set();
});
presenter.SetRemoteTableName(expected);
Assert.IsTrue(are.WaitOne(1000, false), "Event never fired");
Assert.AreEqual(actual, expected);
}
Split the code so that the logic is in a synchronous bit of code that is called by a thin asynchronous wrapper.
Then most of your unit tests can test the synchronous code.
is there a better way than simply sleeping for a bit and then checking for a flag that is set by the callback?
Replace the flag with a wait handle. Instead of setting the flag, set the wait handle. Instead of sleeping and then checking whether the flag is set, wait on the wait handle ... and wait with a timeout, so that if you wake up because of timer expiry instead of waking up because the handle on which you were waiting was fired by the callback, then you know that the test failed (i.e. the callback wasn't invoked within the timeout period).