Why is the property value not instantly updated when multi-threading? C# - multithreading

I have a Task running which updates a Property in another thread.
The moment it updates it, inside a loop it rechecks the variable and often happens that the variable still isn't updated? (a second, two)
Here's an example:
while (true)
{
if (someProperty) // Fails to recognize the set variable of True.
{
// Do something...
}
someProperty = true;
}
Is it a multi-thread issue and those should be synchronized? What would be the best way to solve that?

if this variable is shared between threads, it must be declared as volatile.
https://msdn.microsoft.com/en-us/library/x13ttww7.aspx

Related

How can I implement callback functions in a QObject-derived class which are called from non-Qt multi-threaded libraries?

(Pseudo-)Code
Here is a non-compilable code-sketch of the concepts I am having trouble with:
struct Data {};
struct A {};
struct B {};
struct C {};
/* and many many more...*/
template<typename T>
class Listener {
public:
Listener(MyObject* worker):worker(worker)
{ /* do some magic to register with RTI DDS */ };
public:
// This function is used ass a callback from RTI DDS, i.e. it will be
// called from other threads when new Data is available
void callBackFunction(Data d)
{
T t = extractFromData(d);
// Option 1: direct function call
// works somewhat, but shows "QObject::startTimer: timers cannot be started
// from another thread" at the console...
worker->doSomeWorkWithData(t); //
// Option 2: Use invokeMethod:
// seems to fail, as the macro expands including '"T"' and that type isn't
// registered with the QMetaType system...
// QMetaObject::invokeMethod(worker,"doSomeGraphicsWork",Qt::AutoConnection,
// Q_ARG(T, t)
// );
// Option 3: use signals slots
// fails as I can't make Listener, a template class, a QObject...
// emit workNeedsToBeDone(t);
}
private:
MyObject* worker;
T extractFromData(Data d){ return T(d);};
};
class MyObject : public QObject {
Q_OBJECT
public Q_SLOTS:
void doSomeWorkWithData(A a); // This one affects some QGraphicsItems.
void doSomeWorkWithData(B b){};
void doSomeWorkWithData(C c){};
public:
MyObject():QObject(nullptr){};
void init()
{
// listeners are not created in the constructor, but they should have the
// same thread affinity as the MyObject instance that creates them...
// (which in this example--and in my actual code--would be the main GUI
// thread...)
new Listener<A>(this);
new Listener<B>(this);
new Listener<C>(this);
};
};
main()
{
QApplication app;
/* plenty of stuff to set up RTI DDS and other things... */
auto myObject = new MyObject();
/* stuff resulting in the need to separate "construction" and "initialization" */
myObject.init();
return app.exec();
};
Some more details from the actual code:
The Listener in the example is a RTI DataReaderListener, the callback
function is onDataAvailable()
What I would like to accomplish
I am trying to write a little distributed program that uses RTI's Connext DDS for communication and Qt5 for the GUI stuff--however, I don't believe those details do matter much as the problem, as far as I understood it, boils down to the following:
I have a QObject-derived object myObject whose thread affinity might or might not be with the main GUI thread (but for simplicity, let's assume that is the case.)
I want that object to react to event's which happen in another, non-Qt 3rd-party library (in my example code above represented by the functions doSomeWorkWithData().
What I understand so far as to why this is problematic
Disclaimer: As usual, there is always more than one new thing one learns when starting a new project. For me, the new things here are/were RTI's Connext and (apparently) my first time where I myself have to deal with threads.
From reading about threading in Qt (1,2,3,4, and 5 ) it seems to me that
QObjects in general are not thread safe, i.e. I have to be a little careful about things
Using the right way of "communicating" with QObjects should allow me to avoid having to deal with mutexes etc myself, i.e. somebody else (Qt?) can take care of serializing access for me.
As a result from that, I can't simply have (random) calls to MyClass::doSomeWorkWithData() but I need to serialize that. One, presumably easy, way to do so is to post an event to the event queue myObject lives in which--when time is available--will trigger the execution of the desired method, MyClass::doSomeWorkWithData() in my case.
What I have tried to make things work
I have confirmed that myObject, when instantiated similarly as in the sample code above, is affiliated with the main GUI thread, i.e. myObject.thread() == QApplication::instance()->thread().
With that given, I have tried three options so far:
Option 1: Directly calling the function
This approach is based upon the fact that
- myObject lives in the GUI thread
- All the created listeners are also affiliated with the GUI thread as they are
created by `myObject' and inherit its thread that way
This actually results in the fact that doSomeWorkWithData() is executed. However,
some of those functions manipulate QGraphicsItems and whenever that is the case I get
error messages reading: "QObject::startTimer: timers cannot be started from another
thread".
Option 2: Posting an event via QMetaObject::invokeMethod()
Trying to circumvent this problem by properly posting an event for myObject, I
tried to mark MyObject::doSomeWorkWithData() with Q_INVOKABLE, but I failed at invoking the
method as I need to pass arguments with Q_ARG. I properly registered and declared my custom types
represented by struct A, etc. in the example), but I failed at the fact the
Q_ARG expanded to include a literal of the type of the argument, which in the
templated case didn't work ("T" isn't a registered or declared type).
Trying to use conventional signals and slots
This approach essentially directly failed at the fact that the QMeta system doesn't
work with templates, i.e. it seems to me that there simply can't be any templated QObjects.
What I would like help with
After spending about a week on attempting to fix this, reading up on threads (and uncovering some other issues in my code), I would really like to get this done right.
As such, I would really appreciate if :
somebody could show me a generic way of how a QObject's member function can be called via a callback function from another 3rd-party library (or anything else for that matter) from a different, non QThread-controlled, thread.
somebody could explain to me why Option 1 works if I simply don't create a GUI, i.e. do all the same work, just without a QGraphcisScene visualizing it (and the project's app being a QCoreApplication instead of a QApplication and all the graphics related work #defineed out).
Any, and I mean absolutely any, straw I could grasp on is truly appreciated.
Update
Based on the accepted answer I altered my code to deal with callbacks from other threads: I introduced a thread check at the beginning of my void doSomeWorkWithData() functions:
void doSomeWorkWithData(A a)
{
if( QThread::currentThread() != this->thread() )
{
QMetaObject::invokeMethod( this,"doSomeWorkWithData"
,Qt::QueuedConnection
,Q_ARG(A, a) );
return;
}
/* The actual work this function does would be below here... */
};
Some related thoughts:
I was contemplating to introduce a QMutexLocker before the if statement, but decided against it: the only part of the function that is potentially used in parallel (anything above the return; in the if statement) is--as far as I understand--thread safe.
Setting the connection type manually to Qt::QueuedConnection: technically, if I understand the documentation correctly, Qt should do the right thing and the default, Qt::AutoConnection, should end up becoming a Qt::QueuedConnection. But since would always be the case when that statement is reached, I decided to put explicitly in there to remind myself about why this is there.
putting the queuing code directly in the function and not hiding it in an interim function: I could have opted to put the call to invokeMethod in another interim function, say queueDoSomeWorkWithData()', which would be called by the callback in the listener and then usesinvokeMethodwith anQt::AutoConnection' on doSomeWorkWithData(). I decided against this as there seems no way for me to auto-code this interim function via templates (templates and the Meta system was part of the original problem), so "the user" of my code (i.e. the person who implements doSomeWorkWithData(XYZ xyz)) would have to hand type the interim function as well (as that is how the templated type names are correctly resolved). Including the check in the actual function seems to me to safe typing an extra function header, keeps the MyClass interface a little cleaner, and better reminds readers of doSomeWorkWithData() that there might be a threading issue lurking in the dark.
It is ok to call a public function on a subclass of QObject from another thread if you know for certain that the individual function will perform only thread-safe actions.
One nice thing about Qt is that it will handle foreign threads just as well as it handles QThreads. So, one option is to create a threadSafeDoSomeWorkWithData function for each doSomeWorkWithData that does nothing but QMetaMethod::invoke the non-threadsafe one.
public:
void threadSafeDoSomeWorkWithData(A a) {
QMetaMethod::invoke("doSomeWorkWithData", Q_ARG(A,a));
}
Q_INVOKABLE void doSomeWorkWithData(A a);
Alternatively, Sergey Tachenov suggests an interesting way of doing more or less the same thing in his answer here. He combines the two functions I suggested into one.
void Obj2::ping() {
if (QThread::currentThread() != this->thread()) {
// not sure how efficient it is
QMetaObject::invoke(this, "ping", Qt::QueuedConnection);
return;
}
// thread unsafe code goes here
}
As to why you see normal behaviour when not creating a GUI? Perhaps you're not doing anything else that is unsafe, aside from manipulating GUI objects. Or, perhaps they're the only place in which your thread-safety problems are obvious.

Callback to execute when a thread is finished

Disclaimer (fully editable/removable)
I've done my homework but to the best of my recognition, I can't see the very thing I'd like to know (which is a bit surprising, so I'm sure that a kind soul will flag me as a duplicate - please accept my apology in advance, haha).
Background and anticipated issue
When I start Outlook, I'm performing an update from CRM Dynamics, which takes a while. So, I decided to put the update in a thread. It works as supposed to but there's a button on the ribbon allowing a user to manually call for an update. Anticipating a frantic user, I realize that someone will click the button before the original update is finished and all kinds of excrement may hit the gas redistributive device.
Suggested solution
In order to avoid that, I've put a private property as follows.
private bool KeepYourPantsOn { get; set; }
As long as the said property is true (which it is set to right before I start the updating thread), all the frantic clicking will be either ignored or treated by a calm and informative
MessageBox.Show("Yes, yes... Updating still... Keep your pants on.");
but as soon as the thread is done, I'd like the property to flip over to false enabling the user to manually update Outlook.
Implementation problem
My hick-up is that I haven't found any OnFinished, WhenDone etc. method to call in order to switch the value of KeepYourPantsOn. Moreover, I haven't really seen any suggested solution on how to resolve that (or, rather - I haven't perceived any solution - I might have seen one without realizing that was it, due to ignorance within the area of threaded programming).
You should be able to just set the bool to false as the last line in your thread (or as the last line before looping back to wait on something, if your thread does that).
Note #Tudor comment regarding volatile - just to be sure, do it.
You can create a backing store for your property to hold the value and use a lock whenever you set or get the value to ensure that no concurrency issue arises.
After that, when you start processing on a separate thread, set the value to true and before exiting the method set the value to false.
On user click just check the value of KeepYourPantsOn property and display the message if it is still true.
class YourClass
{
private static readonly object _syncRoot = new object();
private bool _keepYourPantsOn;
public bool KeepYourPantsOn
{
get
{
lock(_syncRoot)
{
return _keepYourPantsOn;
}
}
set
{
lock(_syncRoot)
{
_keepYourPantsOn = value;
}
}
}
private ThreadMethod()
{
KeepYourPantsOn = true; //signal that the update process is starting...
// perform your logic
KeepYourPantsOn = false; //signal that the update process is finished
}
public ManualUpdate()
{
if(KeepYourPantsOn)
MessageBox.Show("Yes, yes... Updating still... Keep your pants on.");
else
Update();
}
}

QObject::moveToThread and executing a member function inside that thread

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.

concurrent access to static methods in java, is synchronization needed?

Do different threads accessing method "foo" have their own copy of local variables, or it is needed to make this method synchronized?
class X {
static returnType foo( Object arg) {
Object localvar;
// perform some calculation based on localvar and arg.
// no non-local variable is used i.e: this is a utility method.
// return something.
}
}
You don't need to synchronize that method. The local variable gets created in the current thread's "memory space" and there is no way that it will get accessed by any other thread (from what you've shown above).
Since the variables used are defined/used in it's own scope there is no need for syncronize the method.
The method should not be synchronized but you should use a final variable arg ie
static returnType foo(final Object arg).

How to do a proper way to copy URL->bstrVal to a global variable?

I have this function inside my program:
void CBar::NavigateComplete2(IDispatch *pDisp, VARIANT *URL)
{
try {
UpdateBar(UpdateNavigateComplete);
} catch (...) {
ASSERT(0);
}
}
I need to have the URL value from URL->bstrVal from this function and to copy it to a global variable so that my other function can easily refer to it.
What is the appropriate way to do this? since my current method destroys the stability of my program..it crash all the time.
I'm not sure I understand the question or the motivation. If all you want to do is, as described in the question, copy the value of URL->bstrVal then the simplest way to to use a wrapper BSTR class for the global.
namespace { // keep global private to .cpp file
CComBSTR globalURL;
}
void CBar::NavigateComplete2(IDispatch *pDisp, VARIANT *URL)
{
if (URL != NULL && URL->vt == VT_BSTR)
globalURL = URL->bstrVal;
Otherwise you should use a raw BSTR and copy it with SysAllocString (and don't forget to SysFreeString it when you're done with the global.
If you don't copy the string (and only copy the pointer) the VARIANT's owner will destroy it giving you a global with a dangling pointer.
Use SysAllocString(URL->bstrVal) to create a copy off the BSTRVAL. you will have to free it when you're done with it using SysFreeString().
Though I have to agree with #Space_C0wb0y that using global varsity for this is error prone. Unless UpdateBar does something asynchronously, you should just pass URL->bstrVal as a parameter to it. And even if UpdateBar schedules asynchronous work, it should still encapsulate creating the BSTR copy and associating it with the asynchronous work, to avoid race between the background code and another NavigateComplete event both trying to access the global var. (Or you have to lock the access to it, which pretty much negates the asynchronous idea, unless you know how to optimize your locks really well)

Resources