Calling QAxWidget method outside of the GUI thread - multithreading

I'm beginning to wonder if this is impossible, but I thought I'd ask in case there's a clever way to get around the problems I'm having.
I have a Qt application that uses an ActiveX control. The control is held by a QAxWidget, and the QAxWidget itself is contained within another QWidget (I needed to add additional signals/slots to the widget, and I couldn't just subclass QAxWidget because the class doesn't permit that). When I need to interact with the ActiveX control, I call a method of the QWidget, which in turn calls the dynamicCall method of the QAxWidget in order to invoke the appropriate method of the ActiveX control. All of that is working fine.
However, one method of the ActiveX control takes several seconds to return. When I call this method, my entire GUI locks up for a few seconds until the method returns. This is undesirable. I'd like the ActiveX control to go off and do its processing by itself and come back to me when it's done without locking up the Qt GUI.
I've tried a few things without success:
Creating a new QThread and calling QAxWidget::dynamicCall from the new thread
Connecting a signal to the appropriate slot method of the QAxWidget and calling the method using signals/slots instead of using dynamicCall
Calling QAxWidget::dynamicCall using QtConcurrent::run
Nothing seems to affect the behavior. No matter how or where I use dynamicCall (or trigger the appropriate slot of the QAxWidget), the GUI locks until the ActiveX control completes its operation.
Is there any way to detach this ActiveX processing from the Qt GUI thread so that the GUI doesn't lock up while the ActiveX control is running a method? Is there something clever I can do with QAxBase or QAxObject to get my desired results?

After some experimentation, I was able to solve this by doing something I thought I'd tried earlier: creating a new QThread and calling QAxWidget::dynamicCall from the new thread. I must not have coded it correctly the first time I tried this solution; after sitting with a co-worker, we were able to get it to work. To be specific, what we did is:
(Step 1) Created a subclass of QThread to represent the thread I need to call dynamicCall().
(Step 2) In the constructor of my QThread, pass in a pointer to my original QAxWidget, and keep the pointer in a member variable.
MyThread::MyThread(QAxWidget* passedWidget) : QThread()
{
actualWidget = passedWidget;
}
(Step 3) In the run() method of the QThread, call the dynamicCall() method of the QAxWidget.
void MyThread::run()
{
QVariant result = actualWidget->dynamicCall(...parms as necessary...);
}
(Step 4) Back in my main code, when I need to execute dynamicCall(), I just call the start() method of MyThread. The start() method will execute run() in its own thread, thus sending the necessary command to the ActiveX object without blocking or stalling the main GUI thread.

If there is no event loop needed, then there is no need NOT to subclass QThread! I think this is the way to solve this without a bunch of signals to the main thread which (more than likely) owns the QAxWidget. The latest docs for Qt 5.3 referring to QThread also bears this out.

Related

SpriteKit windows do not redraw until "applicationDidFinishLaunching" method quits

I use SpriteKit for Mac OS X (not iOS) to run my programs.
At the end of the "applicationDidFinishLaunching" method of the "AppDelegate"-Class I start all things which are needed for initialization. Some methods do not like to be called from a background-thread like setting window-titles, resizing windows and some other tasks. So all these things are done in the main-thread.
Then we come to my problem: I cannot simply run my main program at the end of the "applicationDidFinishLaunching" method, because when I do so, the "applicationDidFinishLaunching" method does not quit until my main program quits. And my main program does not quit, because it shows some animation on the screen directly after starting the program.
In the case, that the "applicationDidFinishLaunching" method does not quit, SpriteKit does not redraw the window, so my animation runs but I see a white window.
After quitting my program, the "applicationDidFinishLaunching" method quits, too, and I see the last picture of the animation.
So I realized a workaround: I now do the initialization in the "applicationDidFinishLaunching" method and then start a background thread which runs my main program.
The "applicationDidFinishLaunching" quits after starting the background-thread and the window is updated as expected. Everything runs fine with the background-thread doing the animation.
And now the problem, I cound not solve: I need to hide the menu bar, not directly when starting the program, but after some time.
NSMenu.setMenuBarVisible(false)
Doing so is no problem when calling from the main-thread but if I hide the menu-bar from my background thread, then I can hide it once, make it visible once, hide it a second time and when making it visible a second time an exception in the AppDelegate Class stops my program:
Thread 1: EXC_BAD_ACCESS (code=EXC_i386_GPFLT)
My idea to solve this problem, was to post an event, which is handeled by the main-thread. But if I post a keyboard event for example, the event-handling is done within the background-thread, too.
Events like selecting a menu by the user, not programmatically are handeled from the main thread but I did not find a way to post an event which is then handeled in the main thread instead of the thread, which contains the sendEvent-command:
NSApplication.sharedApplication().sendEvent(event!) // Called from background-thread
Has anybody an idea of sending an event which is handeled by the main-thread
or
Running my program completely in the main-thread without having the problem, that the window-content is not drawn at all. This second solution would be my favourite, because there are some more things, which make problems within a background thread.
Perhaps I can start my main program from another method, some time after "applicationDidFinishLaunching" has finished.
Some deeper information to the topic above but still no solution:
I discovered, that there exists a function "performSelectorOnMainThread" which can be called from swift like this:
NSApplication.performSelectorOnMainThread(Selector(myFunctionToCall()), withObject: nil, waitUntilDone: true)
This call compiles, my function is called but in my background thread not on the main thread and an error is dumped:
2015-01-17 20:11:09.142 AudioDatabase[4449:2099588] +[NSApplication (null selector)]: unrecognized selector sent to class 0x7fff7b1d8be0
But execution continues. I was not able to call the function on any other than a few types like NSApplication, NSObject, NSThread like a class function. But I never reached the main loop with this.
Another idea was to use NSInvocation, but when I look in the documentation, only the Objective-C Part appears.
It would help, if it was possible, to simply call a function of mine with or without arguments that runs in the main thread and can do there something.
While running my program in a background thread, I discovered a way, to execute neccessary commands in the main-thread asynchronous. To do so, you have to call:
dispatch_async(dispatch_get_main_queue())
{
// This block runs in the main thread
}
So my question was, so show and hide the menu bar without crashing my program. Here are the finished functions which work, when called from a background-thread:
func m_MenuBarShow ()
{
dispatch_async(dispatch_get_main_queue())
{
NSMenu.setMenuBarVisible(true) // Class func, must be called on the Class (NSMenu) and not on the Instance (NSApp.sharedApp.mainMenu)
}
}
func m_MenuBarHide ()
{
dispatch_async(dispatch_get_main_queue())
{
NSMenu.setMenuBarVisible(false) // Class func
}
}
Please note that there is a small restriction on using this: The block is called asynchronous, that means you have to make sure, that it is finished, until doing something with the result. In the case of showing the menu bar this is no problem. But if you want to do something like opening a file, you must handle this.
I will explain this as an answer to another question of mine. Please have a look at: Open File Dialog crashes in Swift

Disposing of ExcelDnaUtil.Application from new thread

I'm using ExcelDNA to develop an XLL.
In it, I have a form living in a DLL to which I pass "ExcelDnaUtil.Application" as a member to facilitate interactions between the form and the instance of Excel running the XLL.
If I launch the form in the main thread using:
form1.show()
when I close the form then close Excel, Process Explorer shows that the Excel process is properly disposed of.
If I launch the form using a new thread:
Dim workerThread As Thread
workerThread = New Thread(Sub() form1.showdialog())
workerThread.Start()
when I close the form and then close Excel, the process remains in Process Explorer. I have been careful not to use two decimal points in any line of code and set the interface member to "nothing" when closing the form. I am not using "ReleaseCOMObject" as other articles have indicated that it is bad-practice.
Question: How do I dispose of the Excel process properly from a separate thread?
It's impossible to get the COM stuff right cross-thread.
You should never talk to the Excel COM object model from another thread. If you follow this one simple rule, you never have to worry about two dots, never have to set anything to Nothing and never have to call any of the ReleaseComObject hacks. And Excel will close nicely.
Since Excel is single-threaded (actually because the Excel COM object model lives in a Single-Threaded Apartment), there is no performance benefit from talking to Excel with another thread - internally it all gets marshalled to the main thread anyway.
If you dare to talk to Excel from another thread, then any COM call could fail, at any time. This is because Excel is still 'alive' and can go into a state where the 'object model is suspended', causing all COM calls to fail (with errors that even a COM message filter can't catch). When would Excel go into such a stubborn mode? When the user does something crazy like click their mouse button, for example.
How then to call back to Excel after you've done some work on another thread? Excel-DNA has a helper that will schedule work to be done back on the main thread, when Excel is in a mode where COM calls are safe. You just call ExcelAsyncUtil.QueueAsMacro(...) with a delegate containing the work to be done. This call can be made at any time from any thread, but the code will only run when ready.
A somewhat clumsy example is this:
Public Module MyFunctions
Dim workerThread As Thread
Public Function OverwriteMe() As Object
Dim caller = ExcelDnaUtil.Application.Caller
workerThread = New Thread( _
Sub()
Thread.Sleep(5000)
ExcelAsyncUtil.QueueAsMacro( _
Sub()
caller.Value = "Done!!!"
End Sub)
End Sub)
workerThread.Start()
Return "Doing it..."
End Function
End Module

How to run one function in another thread

I'm standing in front of a small (maybe not) problem. I have one function which parses XML file (very big xml ~1Gb) so it takes many time (5-6 mins to finish the func). I don't want to use it in GUI-thread because of known issues (mainwindow freezes and nothing happened, so user thinks everything goes wrong). I've tried to solve this problem by using
QtConcurrent::run
But one more problem appeared: if user press X (close button in top right corner) main GUI-thread goes down, but child-thread which was generated my QtConcurrent::run continue his work and I can kill him only by task manager.
I've decided to use QThread instead of QtConcurrent::run6 but I don't understand how can I run MainWindow class function:
void MainWindow::parseXML()
I've tried to create smth like this:
class pThread : public QThread
{
Q_OBJECT
private:
void run();
};
void pThread::run(){
MainWindow::parseXML();
}
But when I'm trying to compile it error appears:
cannot call member function 'void MainWindow::parseXML()' without object
Moreover, I don't know if it possible to update GUI-thread through this method (parseXML function changes statusBar)
What should I do?
The recommended ways to work with threads in Qt is not to inherit from QThread class, see the documentation here and you should be able to do it after that.
And yes it is possible to update the mainwindow from the thread, just code the signals and slots for that functionality, into mainwindow class code a slot that updates the progress and into the class that does the work (the xml parsing you need - there is no reason that functionality should be into the mainwindow class anyway) you code the signal that emit the progress and connect it with mainwindow's slot with Qt::QueuedConnection (note that the default auto-connection will become queued if the objects are in separate threads).
Another option is to use start a QRunnable with QThreadPool. you may want to check documentation. Be ware to wait the spawned threads with QThreadPool::waitForDone().

C++ MultiThreading with visual studio express 2010 Forms Application

I am developing a Windows forms application which connects to a piece of hardware, acquires a lot of data (~1 GSample/sec), processes it, and spits it out to the screen upon a button click. I am now trying to automate the process in a loop that can be started/stopped at any time so I can monitor it whilst tweaking the input to the acquisition hardware. I thinks it's clear that I need to do this on a separate thread, but I'm having a heck of a time trying to do this in c++/cli - I have found a number of good examples using MFC, which is not supported by Express.
Specifically: My task is to press a button which is handled in Form1.h, to call a function in my main file Acquisition.cpp which contains the following code (currently an infinite loop)
void Form1::realTimeUpdate()
{
// live is a boolean variable set by a button on the form
while(live)
{
displayVariance(getVar(getQuadratures(100),nbrSamples));
}
}
I wish to execute this code in a separate thread so that the main program can listen for the user request to stop the operation. Without threading, I currently have to forcefully quit the program (or set it to run a fixed number of times) to stop it.
Is there any suggestions how I might go about running this code on a separate thread?
I've (unsuccessfully) tried a few things already:
Modifying the example given in This Microsoft Example. Problem: requires /clr:oldSyntax option which is incompatible with the other 1300 lines of code in the program.
Trying to do what I'd do in Java (Declare a global thread and start/stop it from any point in the code. Problem: Compiler won't let me declare a global System::Threading.Thread
this beautiful example. Problem: Requires MFC.
Any suggestions would be greatly appreciated!
You can use a BackgroundWorker or a Thread to handle this. You'll need to make sure that the portion of your work that updates the UI is marshaled back to the UI thread, however.
Here is a tutorial on threading in C++/CLI.
For the record, upon Reed's suggestion about using a BackgroundWorker, I sifted through the code at the bottom of this page and modified my code so that:
It created a new backgroundWorker BGWorker in which BGWorker->DoWork() called my realTimeUpdate() function.
A button on the main Form calls either RunWorkerAsync() or CancelAsync() depending on whether or not the process is running (checked by a boolean flag in my main program).
The realTimeUpdate() function is now passed a BackgroundWorker - realTimeUpdate(BackgroundWorker^ worker, DoWorkEventArgs ^ e) After each calculation is complete within the internal loop, it calls worker->ReportProgress(result) function. In the BGWorker->ProgressChanged() function a separate function, upDataUI(int) draws the result on the main form.
Thanks again for the help.

How to create an observableCollection Sortable and multithreading

Here is my problem , I have created a SortableCollection : ObservableCollection
and added a sort method (sort colors).
When I sort The collection with the principal Thread , it works every thing is fine and works
But When I try to sort this customCollection by using an item in the collection I have an expetion : (The calling thread cannot access this object because a different thread owns it).
I have looked in web and I found several solution , One Solution
This type of solution put the collection multithread for insertion , removing moving operation.
But not for the custom sort.
Thanks for help,
WPF classes have thread affinity. What this means is that all changes to those objects must be in the same thread where they were created. It truly is difficult to create a user interface API that is thread-safe, so Microsoft chose to keep it singlethreaded and force run-time checking to make sure of it.
That said, there are a few options you have to perform your sort in a background thread, and then apply it in the UI thread. The first option is to copy your SortableCollection into a plain old List or Array and perform the sort in the background. Once the background thread is complete, you use a Dispatcher to execute code in the UI thread. Every UI element in WPF extends System.Windows.Threading.DispatcherObject and most extend System.Windows.Freezable. The DispatcherObject is where you get the Dispatcher to execute code in the UI thread.
Logically, the execution would be something like this:
public void BackgroundSort()
{
List<T> items = new List<T>(this.ToArray());
BackgroundSortDelegate del = Sort;
del.BeginInvoke(SortCompleted, del);
}
private void SortCompleted(IAsyncResult result)
{
BackgroundSortDelegate del = result.AsyncState as BackgroundSortDelegate;
List<T> items = del.EndInvoke(result);
this.Dispatcher.Invoke(()=>{this.Collection = items;});
}
The short explanation of what happened is that the background worker/delegate is using a copy of the items in this list. Once the sort is complete, we are calling the Dispatcher object and invoking an action. In that action we are assigning the new sorted list back to our object.
The key to assigning the result of any background work within the UI thread is to use the UI's Dispatcher object. There's actually probably a half dozen ways to invoke a background worker in C#, but the approach to get your work in a background thread into the UI thread is the same.

Resources