I suddenly get hundreds of these lines in my console log running a process which uses a progress controller I implemented:
** __NSAutoreleaseNoPool(): Object 0x7afafd0 of class NSCFString autoreleased with no pool in place - just leaking
** __NSAutoreleaseNoPool(): Object 0xd8ca4a0 of class __NSCFData autoreleased with no pool in place - just leaking
I'm in a multithreaded environment on iPhone Simulator, downloading a file from the web using WebClient(). I am puzzled how to deal with this as I have no idea what might cause the problem. The thread that is running the download is embedded in
using ( var oAutoRelease = new NSAutoreleasePool ( ) )
I'm attaching to the WebClient's DownloadProgressChanged method and in there I call a delegate which updates the progress view. If I remove this line, the warnings are gone:
ProgressInfo(ACTION.ReceivingResponse, e.ProgressPercentage);
Calling the delegate in turns will go back to my progress controller and udpate a label:
// iIndicator = the value of e.ProgressPercentage.
oProgressController.CurrentActivity = "Percentage done: " + iInidicator.ToString ( ) + "%";
// ProgressController.CurrentActivity:
this.InvokeOnMainThread(delegate { this.oLblCurrentActivity.Text = value; });
What am I missing here!?
EDIT: I figured out that I had to put another NSAutoReleasePool() around this.InvokeOnMainThread(delegate { this.oLblCurrentActivity.Text = value; });
But why? The whole thing is already in a separate pool.
This link should help you http://blog.datispars.com/tasks-in-background-thread-cocoa-performselectorinbackground/
Each thread should have it's own autorelease pool
Related
I am developing an app in which I want to recognize text in real-time.
At first I was using onTapListener so whenever the user was tapping on the screen the current frame was being captured and after that the text recognition was called.
Right now I want to do this completely real-time so the user will not tap on the screen to capture the current frame. But every current frame is going to be captured until the moment the text of one captured current frame will be recognized.
For this reason, I created a global boolean field name locked that is initialized in false and I use it as a "locker" as you will see in a bit.
private boolean locked = false;
And in a method onUpdateFrame(FrameTime frameTime) I use the above global variable locked. When the first feature points are tracked I "lock" the update. So only the current thread gonna capture the current frame. And if the recognized data is null the I put locked = true so the next frame gonna be captured.
This is my code
public void onUpdateFrame(FrameTime frameTime) {
Frame frame = arFragment.getArSceneView().getArFrame();
// If there is no frame, just return.
if (frame == null) {
return;
}
//Making sure ARCore is tracking some feature points, makes the augmentation little stable.
if(frame.getCamera().getTrackingState()==TrackingState.TRACKING && !locked) {
locked = true;
if (mProgressDialog == null) {
mProgressDialog = ProgressDialog.show(this, "Processing",
"OCR...", true);
} else {
mProgressDialog.show();
}
executor.execute(() -> {
Bitmap b = captureImage();
final String[] text = {getOCRResult(b)};
handler.post(() -> {
if(text[0] != null && !text[0].equals("")){
doSomething();
}
else{
locked = false;
}
}
This is not working though. And my app is crashing immediately when is detecting the surface.
I am getting the following error, and the Toast that the error talks about it refers to a Toast that I have inside the method captureImage()
E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-1
Process: opencv.org, PID: 27860
java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepare()
I cant understand what I am doing wrong.
I heard of semaphores and this is why I asked that on my question. Should i use semaphores , do i need something like that so my app will work. As i understand i need one thread anytime to do the capture of the current frame.
Could someone help me i am a bit lost?
thank you
The reason you are getting this error is that you can't show a toast, or any UI, on a non-UI thread.
The usual way to handle this is to create a 'Handler' on the UI thread and send a message to its message queue asking it to post the thread.
You can see examples in both Java and Kotlin in this answer: Can't create handler inside thread that has not called Looper.prepare()
More info on Handler here: https://developer.android.com/reference/android/os/Handler
This question already has answers here:
How do I update the GUI from another thread?
(47 answers)
Closed 1 year ago.
Currently I am creating a background STA thread to keep the UI responsive but it slows down my function calls on the main thread.
Based on this thread How to update progress bar while working in the UI thread I tried the following but the UI only gets updated after all of the work has finished. I tried playing around with the Dispatcher priorities but none of them seem to work.
What I also tried is adding _frmPrg.Refresh() to my Progress callback but this does not seem to change anything.
Dim oProgress = New Progress(Of PrgObject)(Sub(runNumber)
_frmPrg.Invoke((Sub()
_frmPrg.Status = runNumber
End Sub))
End Sub)
System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke(Sub()
DoLongRunningWork(oProgress, _cancellationToken)
End Sub, System.Windows.Threading.DispatcherPriority.Background)
I can't really help you with your problem, but I'll try to clarify what happens in your posted code.
DoLongRunningWork will be invoked through Dispatcher on the UI thread, when the UI thread is not busy. But once started, it will block the UI thread until it completes. So you can't show a progress this way. Your single chance is, to let DoLongRunningWork run on a background thread. That brings you nothing, if the long-running methods come from office objects, which must be accessed from the UI thread...
The Progress class (see the remarks section) invokes your event handler on the UI thread automatically, so you don't need _frmPrg.Invoke in your event handler.
Maybe you can start a STAthread for your progress form and show it from there. The instance of your Progress class must be created in this thread too, but not before your form is shown to ensure, that the thread becomes a WindowsFormsSynchronisationContext (or you set one explicitly after starting the thread). A plain SynchronisationContext won't work!
At least you get updates in your form this way, but the UI thread of the office app will still be blocked. And of course, any action you make with your progress form must be invoked on the UI thread, if accessing office objects.
After reading some other posts, I decided to suggest another solution. My previous answer still contains usable information, so I'll leave it there. I'm not familiar with VB.NET syntax, so the samples are in C#. I have tested the code in a VSTO plugin for PowerPoint, but it should run in any office application.
Forget the Progress class and background threads. Run everything on the UI thread!
Now use some async code. To stay on the UI thread, we need a "good" SynchronizationContext.
private static void EnsureWinFormsSyncContext()
{
// Ensure that we have a "good" SynchronisationContext
// See https://stackoverflow.com/a/32866156/10318835
if (SynchronizationContext.Current is not WindowsFormsSynchronizationContext)
SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
}
This is the event handler of a button. Note the manually added async keyword. The SynchronizationContext.Current gets resetted again and again, so ensure the good one in the EventHandler:
private async void OnButtonClick(object sender, EventArgs e)
{
EnsureWinFormsSyncContext();
// Return from event handler, ensure that we are really async
// See https://stackoverflow.com/a/22645114/10318835
await Task.Yield();
await RunLongOnUIThread();
}
This will be the worker method, also running on the UI thread.
private async Task RunLongOnUIThread()
{
//Dummy code, replace it with your code
var pres = addIn.Application.Presentations.Add();
for (int i = 0; i < 100; i++)
{
Debug.Print("Creating slide {0} on thread {1}", i, Thread.CurrentThread.ManagedThreadId);
// If you have some workloads that can be run on a background
// thread, execute them with await Task.Run(...).
try
{
var layout = pres.Designs[1].SlideMaster.CustomLayouts[1];
var slide = pres.Slides.AddSlide(i + 1, layout);
var shape = slide.Shapes.AddLabel(Microsoft.Office.Core.MsoTextOrientation.msoTextOrientationHorizontal, 0, 15 * i, 100, 15);
shape.TextFrame.TextRange.Text = $"Text on slide {i + 1}";
}
catch (Exception ex)
{
Debug.Print("I don't know what am I doing here, I'm not familiar with PowerPoint... {0}", ex);
}
// Update UI
statusLabel.Text = $"Slide {i + 1} done";
progressBar1.Value = i + 1;
// This is the magic! It gives the main thread the opportunity to update the UI.
// It also processes input messages so you need to disable unwanted buttons etc.
await IdleYield();
}
}
The following method is for Windows Forms Applications where it does the job perfect. I've tried it also in PowerPoint. If you are facing problems, try the WPF flavour with await Dispatcher.Yield(DispatcherPriority.ApplicationIdle) instead of await IdleYield().
private static Task IdleYield()
{
var idleTcs = new TaskCompletionSource<bool>();
void handler(object s, EventArgs e)
{
Application.Idle -= handler;
idleTcs.SetResult(true);
}
Application.Idle += handler;
return idleTcs.Task;
}
Here are the (clickable) links to the answers that I used (I can't put them in the code-blocks...).
Incorrect async/await working, Excel events in Excel Application Level Add-in
When would I use Task.Yield()?
Task.Yield - real usages?
If in your real code something runs not as expected, check the thread you are running on and SynchronizationContext.Current.
I am trying for days now to find a proper solution to the following problem(stated below), and I have no more ideas now. Therefore, I need help from more experienced devs:
I have a class independant from QT (and I want it to stay like this) that generate openCV images in a secundary thread. Then it raise an event which pass the images.
while (1)
{
if (timerActived & this->_camReady)
{
vector<Mat>* images = new vector<Mat>;
images = this->AcquireImg();
__raise this->frameAcquired(images);
}
this_thread::sleep_for(chrono::milliseconds(_frameTimeLaps));
}
This event is hooked by my MainWindow and a method is supposed to display my images on my GUI.
void MainWindow::displayFrame(vector<Mat>* frames) {
vector<Mat>* frames2 = new vector<Mat>();
frames2 = frames;
for (int i = 0; i < frames2->size(); ++i) {
this->camFrames->at(i)->showImage(frames2->at(i));
}
}
During the runTime, when the Main Thread access the images I get the following error :
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread.
I understand that I am not using threads properly, but I have no idea how to create an asynchronous event now.
Thank you for help,
Valentin
EDIT 1 :
It seems to me that the real question is : can I use normal std::thread and native event to communicate with the main Qthread ?
Here is my solution to solve the problem, after all.
The idea is to give the main thread access to the Mat coming from the second thread. So I modified my function displayFrame like this :
void MainWindow::displayFrame(vector<Mat>* frames) {
//QThread::
QThread* this_thread = QThread::currentThread();
FrameWrapper* worker = new FrameWrapper();
worker->moveToThread(this_thread);
QObject::connect(worker, SIGNAL(frameSent(vector<Mat>*)), this, SLOT(showImg(vector<Mat>*)));
emit worker->frameSent(frames);
//this->camFrames->at(0)->showImage(frame);
}
The new function showImg is doing the job of the old displayFrame. The signal/slot process permit to access image from the GUI Thread as wanted.
I'm using SHGetFileInfo function for getting icons for folders and different file types. According to MSDN call of this function should be done from background thread and before call Component Object Model (COM) must be initialized with CoInitialize or OleInitialize.
My code looks like this:
public void SetHlinkImage(string path)
{
Shell32.OleInitialize(IntPtr.Zero);
Task task = Task.Factory.StartNew(() => { LoadIcons(path); });
}
private void LoadIcons(string path)
{
image = GetHlinkImage(path);
if (OwnerControl.InvokeRequired)
layout.ModuleControl.BeginInvoke((MethodInvoker)delegate ()
{
Shell32.OleUninitialize();
});
}
public Icon GetHlinkImage(string path)
{
uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_ATTRIBUTES | Shell32.SHGFI_SMALLICON;
Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
IntPtr result = Shell32.SHGetFileInfo(path,
Shell32.FILE_ATTRIBUTE_DIRECTORY,
ref shfi,
(uint)Marshal.SizeOf(shfi),
flags);
Icon icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone();
WinApi.DestroyIcon(shfi.hIcon); // cleanup
return icon;
}
Mostly the problem appears after first call of the code and as result I get an exception when I tried to create Icon from icon handle:
System.ArgumentException: Win32 handle that was passed to Icon is not
valid or is the wrong type
And further calls of the code work without problems.
Actually behaviour also somehow depends on the test system. It is hardly possible to reproduce this issue on Windows10 systems but on Windows 7 it happens quite often.
Has anyone experienced this problem?
From comment of Hans Passant:
Calling OleInitialize() is pointless, the CLR already initializes COM before it starts a thread. And it failed, something you cannot see because you are not checking its return value. Not knowing that, it just spirals into undiagnosable misery from there. Yes, more of it on Win7. You must provide an STA thread, if this needs to run in the background then consider this solution.
Problem:
I have a private variable that is available during the startup of a threaded object, but is out of scope when it is used later (via a signal and slot call).
Details:
I have an application that I'm developing in Qt5 for both linux and windows.
Currently it works as expected under linux (where development began), but now
that I'm trying to stand it up on windows 7 (I didn't have a copy of windows initially) I have run into this problem where (on windows only) my private variables go out of scope after the thread initializes.
Question:
What is wrong with my object/thread structure such that the variable scope is fine under Linux, but not in windows? I thought that was the kind of "behind the scenes" stuff Qt took care of? (clearly not)
More Detail:
The order of operation goes like this
Instantiate an object
Move the object into a thread
Get the thread's start signal and call an init function in the object
Later, get data and emit a signal to the threaded object
Threaded object processes data
The code outlining the steps above is summarized below.
void MyWorkerClass::init()
{
// ... bunchOCode
procThread = new QThread; // <-- procThread - private to MyWorkerClass
procObj = new Processor(startupData); // <-- procObj - private to MyWorkerClass
procObj->moveToThread(procThread);
connect(procThread, SIGNAL(started()), procObj, SLOT(doStart()));
connect(this, SIGNAL(dataIsReady(void *)), procObj, SLOT(processMsgs(void *)));
procThread->start();
ok = waitforProcSetup();
// ... Life is good, do more stuff
}
class Processor : public QObject
{
// ... Other
// ... stuff
private slots:
void doStart();
void processMsgs(void * buffer);
private:
QHash<QString, bool> process;
}
void Processor::doStart() // <-- private slot
{
// ... take care of init stuff that couldn't be done in constructor
// Variable is valid here and I can work with it.
foreach(site, locations.uniqueKeys()) {
process[site] = true; // <-- works like a champ
qDebug() << QString("%1 => %2").arg(site).arg(process[site]);
}
}
void Processor::processMsgs(void * buffer) // <-- buffer is malloc'd memory and works fine
{
// ... When MyWorkerClass gets some data it emits a signal that is connected
// to this private slot.
// Simply trying to examine the variable causes a segfault (because it's uninitialized here)
qDebug() << "... processMsgs:" << process.isEmpty(); // <-- wets the bed
}
.
In trying to improve my question, by following the suggestions from the people who commented, I found out what was going on. I was working on creating a small working version of the example I posted (thanks Kuba Ober). The "error" I was encountering was a segmentation fault that could consistently be recreated with the debug line:
qDebug() << "... processMsgs:" << process.isEmpty(); // <-- wets the bed
Specifically, the private QHash variable "process" was useable when I called it the first time (after the thread was up and running)
connect(procThread, SIGNAL(started()), procObj, SLOT(doStart()));
but that same variable acted like it had gone out of scope when I tried to call it the second time
connect(this, SIGNAL(dataIsReady(void *)), procObj, SLOT(processMsgs(void *)));
The signal (dataIsReady(void *)) for this second call is an explicit "emit" that the worker class does when it's collected some data that can be processed. I tried to make that clear in the comments of the example pseudocode, but I didn't take into account that the comment code I included wouldn't stand out that well since it's all grey.
What was really going on was right after I filled "process[site]" with data I also looped over a quint64 array filling it with data too. The loop went 1 element too far and wrote into the "process" variable, making it look to me like it had gone out of scope. In linux it was purely coincidental that it didn't segfault (likely there was padding between the array and the QHash), but the windows runtime exposed the error for the first time.