I want to call a function to delete files and folders from the system in a parallel thread called by QtConcurrent::run() (Qt for Embedded Linux 4.8). Using only a QFuture<bool> with QFuture::waitForFinished() to grab the result (I need to run some code right after the operation), I was able to make the system work.
But I want to display the ongoing result of the operation in a QProgressBar derived class with its setValue(int) called via signals and slots mechanism from inside the delete function, and what I get with the above method is a freezed main thread while the operation isn't finished, and that is inadmissible.
So I though about using QFutureWatcher<bool> and connecting it's finished() signal to another slot containing the remaining code to be run after the delete operation is finished.
The problem I'm facing is that, when I do this, the delete function is simply not run by QtConcurrent::run()! I checked that with printed messages to Terminal. Everything that occurs is that the QFutureWatcher calls its finished() signal without any execution of the delete files function (and that also happens if I use QFutureWatcher::waitForFinished()).
Is this some bug from Qt?
Regarding code, it's pretty exactly as in Qt Assistant: create the QFuture and QFutureWatcher globally, connect the finished() signal with the slot, call QtConcurrent::run(), and setFuture() to the future. Nothing special.
Any help appreciated.
EDIT
Following the request of Kuba, here is the relevant part of the code:
//Declared globally in the .cpp
QFuture<bool> future;
QFutureWatcher<bool> watcher;
//
void SelectRecordToDeleteWidget::slotDeleteRecordStateMachine()
{
switch (deleteRecordStateMachine)
{
case PrepareToDelete:
{
//...
connect(&watcher,SIGNAL(finished()),this,SLOT(slotDeleteRecordStateMachine()),Qt::UniqueConnection);
//...
}
break;
case DeleteRecords:
{
//...
future = QtConcurrent::run(removeFiles, QString(DEFAULT_RECORD_DIR) + "/" + recordList.at(aaa).second.second, poProgressDialog, &itemCounter);
watcher.setFuture(future);
qApp->processEvents();
//...
}
break;
case FinishDelete:
{
//Run code after deleting files
}
break;
default:
break;
}
}
This is all the code using QFuture and QFutureWatcher. The removeFiles is as follows (not forgetting that it works well without QFutureWatcher):
bool removeFiles(const QString dirName, Interface::ProgressDialog* const poProgressDialog, qint32* const itemDeletedCounter)
{
bool result = true;
try
{
QDir dir(dirName);
if (dir.exists())
{
Q_FOREACH (QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst))
{
// if (Q_UNLIKELY(poProgressDialog->wasCanceled()))
// break;
if (info.isDir())
{
result = removeFiles(info.absoluteFilePath(),poProgressDialog,itemDeletedCounter);
if (!result)
return result;
}
else
{
result = QFile::remove(info.absoluteFilePath());
if (!result)
return result;
if (!QMetaObject::invokeMethod(poProgressDialog, "setValue",
Qt::BlockingQueuedConnection,
Q_ARG(qint32, *itemDeletedCounter)))
{
mDebugS(QString("removeFiles: %1QMetaObject::invokeMethod(poProgressDialog, \"setValue\"... failed!"));
}
++(*itemDeletedCounter);
// mDebugS(QString("removeFiles: %1").arg(*itemDeletedCounter));
}
}
result = dir.rmdir(dirName);
}
}
catch (...)
{
const QString strTemp = QString("An error in a call to removeFiles");
mDebugS(strTemp);
mLog(strTemp);
}
return result;
}
Related
In the following class, the _busy field acts as a semaphore; but, in "simultaneous" situations it fails to guard!
class Task {
_busy = false;
async run(s) {
try {
if (this._busy)
return;
this._busy = true;
await payload();
} finally {
this._busy = false;
}
}
}
The sole purpose of the run() is to execute the payload() exclusively, denying all the other invocations while it's still being carried on. In other words, when "any" of the invocations reach to to the run() method, I want it to only allow the first one to go through and lock it down (denying all the others) until it's done with its payload; "finally", it opens up once it's done.
In the implementation above, the racing condition do occur by invoking the run() method simultaneously through various parts of the app. Some of the invocations (more than 1) make it past through the "guarding" if statement, since none of them are yet reached to the this._busy = true to lock it down (they get past simultaneously). So, the current implementation doesn't cut it!
I just want to deny the simultaneous invocations while one of them is already being carried out. I'm looking for a simple solution to only resolve this issue. I've designated the async-mutex library as a last resort!
So, how to implement a simple "locking" mechanism to avoid racing conditions that bypass the guard statement in simultaneous actions?
For more clarification, as per the comments below, the following is almost the actual Task class (without the irrelevant).
class Task {
_cb;
_busy = false;
_count = 0;
constructor(cb) {
this._cb = cb;
}
async run(params = []) {
try {
if (this._busy)
return;
this._busy = true;
this._count++;
if (this._count > 1) {
console.log('Race condition!', 'count:', this._count);
this._count--;
return;
}
await this._cb(...params);
} catch (err) {
await someLoggingRoutine();
} finally {
this._busy = false;
this._count--;
}
}
}
I do encounter with the Race condition! log. Also, all the task instances are local to a simple driver file (the instances are not passed down to any other function, they only wander as local instances in a single function.) They are created in the following form:
const t1 = new Task(async () => { await doSth1(); /*...*/ });
const t2 = new Task(async () => { await doSth2(); /*...*/ });
const t3 = new Task(async () => { await doSth3(); /*...*/ });
// ...
I do call them in the various library events, some of which happen concurrently and causing the "race condition" issue; e.g.:
someLib.on('some-event', async function() { /*...*/ t1.run().then(); /*...*/ });
anotherLib.on('event-2', async function() { /*...*/ t1.run().then(); /*...*/ });
Oh god, now I see it. How could I have missed this so long! Here is your implemenation:
async run() {
try {
if (this._busy)
return;
...
} finally {
this._busy = false;
}
}
As per documentations:
The Statements in the finally block are executed before control flow exits the try...catch...finally construct. These statements execute regardless of whether an exception was thrown or caught.
Thus, when it's busy and the flow reaches the guarding if, and then, logically encounters the return statement. The return statement causes the flow to exit the try...catch...finally construct; thus, as per the documentations, the statements in the finally block are executed whatsoever: setting the this._busy = false;, opening the thing up!
So, the first call of run() sets this._busy as being true; then enters the critical section with its longrunning callback. While this callback is running, just another event causes the run() to be invoked. This second call is rationally blocked from entering the critical section by the guarding if statement:
if (this._busy) return;
Encountering the return statement to exit the function (and thus exiting the try...catch...finally construct) causes the statements in the finally block to be executed; thus, this._busy = false resets the flag, even though the first callback is still running! Now suppose a third call to the run() from yet another event is invoked! Since this._busy is just set to false, the flow happily enters the critical section again, even though the first callback is still running! In turn, it sets this._busy back to true. In the meantime, the first callback finishes, and reaches the finally block, where it set this._busy = false again; even though the other callback is still running. So the next call to run() can enter the critical section again with no problems... And so on and so forth...
So to resolve the issue, the check for the critical section should be outside of the try block:
async run() {
if (this._busy) return;
this._busy = true;
try { ... }
finally {
this._busy = false;
}
}
I am working on a small tool to schedule p4 sync daily at specific times.
In this tool, I want to display the outputs from the P4API while it is running commands.
I can see that the P4API.net has a P4Callbacks class, with several delegates: InfoResultsDelegate, TaggedOutputDelegate, LogMessageDelegate, ErrorDelegate.
My question is: How can I use those, I could not find a single example online of that. A short example code would be amazing !
Note: I am quite a beginner and have never used delegates before.
Answering my own questions by an example. I ended up figuring out by myself, it is a simple event.
Note that this only works with P4Server. My last attempt at getting TaggedOutput from a P4.Connection was unsuccessful, they were never triggered when running a command.
So, here is a code example:
P4Server p4Server = new P4Server(syncPath);
p4Server.TaggedOutputReceived += P4ServerTaggedOutputEvent;
p4Server.ErrorReceived += P4ServerErrorReceived;
bool syncSuccess = false;
try
{
P4Command syncCommand = new P4Command(p4Server, "sync", true, syncPath + "\\...");
P4CommandResult rslt = syncCommand.Run();
syncSuccess=true;
//Here you can read the content of the P4CommandResult
//But it will only be accessible when the command is finished.
}
catch (P4Exception ex) //Will be caught only when the command has completely failed
{
Console.WriteLine("P4Command failed: " + ex.Message);
}
And the two methods, those will be triggered while the sync command is being executed.
private void P4ServerErrorReceived(uint cmdId, int severity, int errorNumber, string data)
{
Console.WriteLine("P4ServerErrorReceived:" + data);
}
private void P4ServerTaggedOutputEvent(uint cmdId, int ObjId, TaggedObject Obj)
{
Console.WriteLine("P4ServerTaggedOutputEvent:" + Obj["clientFile"]);
}
I'm trying to make my MVC controller action run asynchronously under .NET 4.0. However, none of my attempts have given me the results I want. I have the following action:
public ActionResult ImportXml()
{
try
{
if (_importRunning)
return Content("Already running");
var obj = new object();
lock (obj)
{
_importRunning = true;
Thread.Sleep(20000);
//_employesImportService.ImportXml();
_importRunning = false;
}
return Content("Done");
}
catch (Exception e)
{
return Content(e.Message);
}
}
When I run two browsers simultaneously that call this action, both seem to wait the 20 seconds I set in the Thread.Sleep(20000). I though that using the lock mechanism would block one request and return the "Already running" content immediately. I'm using .NET 4.0 and I don't have the option of using async await. But is there another way of implementing this so that one of the requests responds quickly?
Currently I have a code that is crashing (SEGFAULT) on me.
I am trying to compare a big amount of images that are in my drive to their counter parts in a server.
To speed up the process I get the image from the server and compare the images on a different thread.
From what I already tried and debugged, the issue is in getting the image from the server (that is why the other calls are commented out).
Also if I run without the QtConcurrent::run it does not crash, but if I put semaphore concurrentComparisons with only one resorce, it will crash.
Finally I also get the following errors
QObject::connect: Cannot connect (null)::configurationAdded(QNetworkConfiguration) to QNetworkConfigurationManager::configurationAdded(QNetworkConfiguration)
QObject::connect: Cannot connect (null)::configurationRemoved(QNetworkConfiguration) to QNetworkConfigurationManager::configurationRemoved(QNetworkConfiguration)
QObject::connect: Cannot connect (null)::configurationChanged(QNetworkConfiguration) to QNetworkConfigurationManager::configurationChanged(QNetworkConfiguration)
QObject::connect: Cannot connect (null)::onlineStateChanged(bool) to QNetworkConfigurationManager::onlineStateChanged(bool)
QObject::connect: Cannot connect (null)::configurationUpdateComplete() to QNetworkConfigurationManager::updateCompleted()
Any help would be very appreciated.....
Relevant code:
QSemaphore FileComparisonInfo::concurrentComparisons(1);
QtConcurrent::run( [this, localPath, imageURL]()
{
ImageComparer cmp;
FileComparisonInfo::concurrentComparisons.acquire();
//cmp.setImageLeftPath(localPath);
cmp.setImageRightPath(imageURL);
//cmp.createDifferenceImage();
FileComparisonInfo::concurrentComparisons.release();
});
void ImageComparer::setImageRightPath(QString path)
{
this->rightImagePath = path;
this->imageRight = getImage(path);
}
QImage* ImageComparer::getImage(QString path)
{
QUrl url(path);
QFile file(path);
if(file.exists())
{
return new QImage(path);
}
else if(url.isValid())
{
return getImageFromURL(path);
}
}
QImage* ImageComparer::getImageFromURL(QString url)
{
QNetworkAccessManager * tempNAM = new QNetworkAccessManager();
QNetworkReply *imageConnection = tempNAM->get( QNetworkRequest( QUrl( url ) ));
QEventLoop loop;
connect(imageConnection, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
QImage * downloadedImage;
if(imageConnection->error() != QNetworkReply::NoError)
{
qDebug() << imageConnection->errorString();
downloadedImage = new QImage();
}
else
{
QByteArray data = imageConnection->readAll();
downloadedImage = new QImage(QImage::fromData(data));
}
tempNAM->deleteLater();
imageConnection->deleteLater();
return downloadedImage;
}
Unfortunately this had nothing to do with the code.
One of the images was corrupted and was segfaulting in the comparison.
I am using timers with resource ID added and based on WM_TIMER message.
I would like to call a routine like DrunkenDragon() on OnTimer() but for only once after SetTimer(id,10sec,NULL) was called. We know that Call to KillTimer() inside DrunkenDragon() routine would fix the solution. Is it okay to go with this, or am I missing out something great with timers.
(Only answering this in case someone else comes across it like I did and was unsatisfied with the answers available)
So, in WindowClass.h, what you can do is an enumeration of the timer identifiers you want to use. While you certainly can use raw numeric values, using symbols is probably easier to work with in the long run.
class WindowClass : CWnd
{
// other parts of the interface...
protected:
enum
{
TIMER_MAIN_UPDATE = 1,
TIMER_PLASTERED_DRAGON
};
};
Meanwhile, back at in WindowClass.cpp,
int WindowClass::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// { ... other initialization code }
// In case you want to do other types of updates at regular intervals.
SetTimer(TIMER_MAIN_UPDATE, 1000, NULL);
// Note the symbolic identifiers.
SetTimer(TIMER_PLASTERED_DRAGON, 10000, NULL);
return 0;
}
That's only any good if you want to do it 10 seconds after the window's been created, though. You can also just call SetTimer() in some other event handler whenever you'd like:
void WindowClass::OnJustGotPaid()
{
// { ... other handling }
// Since our dragon is a real lightweight, it apparently only takes
// 10 seconds to get him puking up flaming vomit.
SetTimer(TIMER_PLASTERED_DRAGON, 10000, NULL);
}
When it comes time for the actual event to be handled, it is typically handled in the Windows OnTimer() callback. A timer event can be directed to a different (custom) callback, if desired, by specifying a valid function pointer in SetTimer()'s third parameter instead of NULL.
void WindowClass::OnTimer(UINT_PTR p_timer_id)
{
switch(p_timer_id)
{
default:
break;
case TIMER_MAIN_UPDATE:
// { ... main update code }
break;
case TIMER_PLASTERED_DRAGON:
// Killing the timer first in case DrunkenDragon() takes a good
// long while for whatever reason.
KillTimer(TIMER_PLASTERED_DRAGON);
DrunkenDragon();
break;
}
}
int CYourDialog::OnInitDialog()
{
__super::OnInitDialog();
SetTimer(0x10, 10000, NULL);
return true;
}
void CYourDialog::OnTimer(UINT_PTR ignore)
{
DrunkenDragon();
}
And ensure you have ON_WM_TIMER in message-map.
You are not missing anything and you would have to use KillTimer for system to stop generating WM_TIMER messages.
You can also use CreateTimerQueueTimer and set parameters the way a callback is called only once.
See this for more details.