use QtConcurrent but main thread freeze again in QT - multithreading

There are thousand of images that want to make thumnail and load them in listWidget.
I use QtConcurrent to do it in a separate thread but the problem is that the main thread be freeze while they are loaded.
here is my new thread:
void Dialog::on_treeView_doubleClicked(const QModelIndex &index)
{
connect(&secthread , &thread2::loadPicture , this ,&Dialog::on_loadPicture );
QFuture<void> future2=QtConcurrent::run(&this->secthread , &thread2::start);
}
and function to show images :
void Dialog::on_loadPicture()
{
ui->listWidget->setViewMode(QListWidget::IconMode);
ui->listWidget->setIconSize(QSize(80,100 ));
ui->listWidget->setResizeMode(QListWidget::Adjust);
ui->progressBar->setMaximum(vec.size());
ui->progressBar->setMinimum(l.min());
QDirIterator it(path , QDirIterator::Subdirectories);
connect(&l , SIGNAL(signalProgress(int)) , ui->progressBar , SLOT(setValue(int)));
l.emit50();
while(it.hasNext())
{
item=new QListWidgetItem(QIcon(it.next()) , QString("1 (" + (QString::number(9)) + ").jpg" ));
QVariant pathData(it.filePath());
item->setData(Qt::UserRole , pathData);
ui->listWidget->addItem(item);
this->repaint();
ui->listWidget->repaint();
n++;
emit l.signalProgress(n);
}
}
thanks a bunch.

Related

Running an std::async in a loop. How to get consistent results?

I try to parallelize calculations and write the results in order to a vector.
I'm using a std::async. The program works perfectly with a short pause (ref. the commented line). Without this pause, the program crashes.
The Code ( in an online IDE to modify & test the MCVE :
class AsyncDispatcher {
public:
/* Data is a custom class with data that contains a ID.
* The object contains no
* links or pointers.*/
vector<Data> calcResult(vector<Params> params) {
vector<Data> result;
vector<std::future<NumberedData>> futures;
threadID = 0;
for (auto param : params) {
futures.push_back(((std::async(std::launch::async, [&]() {
this_thread::sleep_for(chrono::milliseconds(100)); // not workable without this command
//^^^^^^^^^^^^^^^^^^^^^^^^^
return NumberedData(filler.createData(param, threadID), threadID);
}))));
threadID++;
}
for (auto& f : futures) {
result.push_back(f.get().data);
}
return result;
}
AsyncDispatcher() : threadID(0) {}
private:
int threadID;
Filler filler;//fills an Data with numbers
};

xSemaphoreGive() gets stuck when used by different threads

I am working on STM32F756ZG with FreeRTOS. I have one network thread that is made using osThreadDef() which is a part of the CMSIS-RTOS API. I also have other tasks running that are created using xTaskCreate() which is a part of the freeRTOS API.
I have a Semaphore that is shared by a tempSensor and EEPROM. In the network thread, the I try to get the values for IP address from the EEPROM using I2C protocol. It successfully takes the Semaphore using xSemaphoreTake() but when its time to give up the Semaphore using xSemaphoreGive() it gets lost and when I hit pause it stays in I2C_WaitOnFlagUntilTimeout().As a result it never loads the webpage.
The other tasks run fine and the temp sensor that also uses I2c and sempahore returns the values correctly.
So my question is if this problem is created because of using semaphore between two threads each generated by different OS API. I am really struggling with this and any help would be really appreciated. Thanks a lot!
I am adding a little code snippet here.
/* Init networking thread */
osThreadDef(Start, StartNetworkThread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE * 2);
osThreadCreate (osThread(Start), NULL);
start_threads(3);
HAL_ADC_Start_DMA(&hadc1, (uint32_t*) adc1vals, 1);
HAL_ADC_Start_DMA(&hadc2, (uint32_t*) adc2vals, 1);
xTaskCreate (vADC1, "vADC1", configMINIMAL_STACK_SIZE, NULL, uxPriority + 3, ( TaskHandle_t * ) NULL );
xTaskCreate (vADC2, "vADC2", configMINIMAL_STACK_SIZE, NULL, uxPriority + 3, ( TaskHandle_t * ) NULL );
xTaskCreate (vPIDloop, "vPIDloop", configMINIMAL_STACK_SIZE + 100, NULL, uxPriority + 2, ( TaskHandle_t * ) NULL );
xTaskCreate (vIO, "vIO", configMINIMAL_STACK_SIZE + 512, NULL, uxPriority + 1, ( TaskHandle_t * ) NULL ); //Run IO at least important priority
xTaskCreate (vControl, "vControl", configMINIMAL_STACK_SIZE + 512, NULL, uxPriority + 1, ( TaskHandle_t * ) NULL ); //Run control at least important priority
This is how my Semaphore is initialized:
// Initialize the semaphore that controls eeprom access
xI2C3Semaphore = xSemaphoreCreateMutex();
if( xI2C3Semaphore ==NULL)
{
while(1);
}
Following is the code for when I am reading the EEPROM:
int result = 0;
NvVarsEeprom_t eepromVar;
memset( &eepromVar, 0xff, sizeof(eepromVar) );
if( xI2C3Semaphore != NULL )
{
// Wait forever for semaphore
if( xSemaphoreTake( xI2C3Semaphore, (TickType_t)10 ) == pdTRUE )
{
// count = uxSemaphoreGetCount(xI2C3Semaphore);
// Read from EEPROM
if( nvdata_read((char *)&eepromVar, sizeof(eepromVar), addr) != HAL_OK )
{
//vTaskDelay(5);
if( nvdata_read((char *)&eepromVar, sizeof(eepromVar), addr) != HAL_OK )
{
return ERR_EEPROM;
}
}
//count = uxSemaphoreGetCount(xI2C3Semaphore);
// Give up the semaphore
if(xSemaphoreGive( xI2C3Semaphore ) != pdTRUE)
{
while(1);
}
// count = uxSemaphoreGetCount(xI2C3Semaphore);
}
}
if( result == 0 )
{
eepromVar.valid = NVP_VALID;
}
if( eepromVar.valid == NVP_VALID )
{
strncpy( buf, eepromVar.str, EepromVarSize-1 );
buf[EepromVarSize-1] = '\0';
}
else
{
return ERR_EEPROM;
}
return result;
The next code snippet is when I am reading from the temp sensor:
int tempC = 0;
if( xI2C3Semaphore != NULL )
{
// Wait forever for semaphore
if( xSemaphoreTake( xI2C3Semaphore, (TickType_t)10 ) == pdTRUE )
{
// Read from I2C3
tempC = heatSink_read();
// Give up the semaphore
if(xSemaphoreGive( xI2C3Semaphore ) != pdTRUE)
{
while(1);
}
}
}
return tempC;
When I jump from the bootloader to the application and try to read values from the EEPROM, I can take the Semaphore but I does not give it back using xSemaphoreGive().
First of all, make sure semaphore got initialized properly, like this:
if ((SemId_I2C1_Rx = xSemaphoreCreateBinary()) == NULL) { goto InitFailed; };
Secondly, make sure you are using proper function for giving the semaphore.
If it is given from an Interrupt, you have to use
xSemaphoreGiveFromISR(SemId_I2C1_Rx, NULL);

TcpListener.AcceptSocket( ) behavior: gets stuck in one app upon termination, but does not in another?

I have two TCP-server apps that are based on the same code, but for some reason exhibit different behavior and i'm ready to pull my hair out trying to figure out why. The code pattern is as follows:
public class TcpServer
{
public static void Start( bool bService )
{
..
oTcpListnr= new TcpListener( ip, iOutPort );
aTcpClient= new ArrayList( );
bListen= true;
oTcpListnr.Start( );
thOutComm= new Thread( new ThreadStart( AcceptTcpConn ) );
thOutComm.Name= "App-i.AcceptTcpConn";
thOutComm.Start( );
..
}
public static void Stop( )
{
bListen= false;
if( thOutComm != null )
{
thOutComm.Join( iTimeout );
thOutComm= null;
}
if( oTimer != null )
{
oTimer.Change( Timeout.Infinite, Timeout.Infinite );
oTimer.Dispose( );
}
}
public static void AcceptTcpConn( )
{
TcpState oState;
Socket oSocket= null;
while( bListen )
{
try
{
// if( oTcpListnr.Pending( ) )
{
oSocket= oTcpListnr.AcceptSocket( );
oState= new TcpState( oSocket );
if( oSocket.Connected )
{
Utils.PrnLine( "adding tcp: {0}", oSocket.RemoteEndPoint.ToString( ) );
Monitor.Enter( aTcpClient );
aTcpClient.Add( oState );
Monitor.Exit( aTcpClient );
oSocket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.DontFragment, true );
oSocket.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.DontLinger, true );
// / oSocket.BeginReceive( oState.bData, 0, oState.bData.Length, SocketFlags.None, // no need to read
// / new AsyncCallback( AsyncTcpComm ), oState ); // for output only
}
else
{
Utils.PrnLine( "removing tcp: {0}", oSocket.RemoteEndPoint.ToString( ) );
Monitor.Enter( aTcpClient );
aTcpClient.Remove( oState );
Monitor.Exit( aTcpClient );
}
}
// Thread.Sleep( iTcpWake );
}
#region catch
catch( Exception x )
{
bool b= true;
SocketException se= x as SocketException;
if( se != null )
{
if( se.SocketErrorCode == SocketError.Interrupted )
{
b= false;
if( oSocket != null )
Utils.PrnLine( "TcpConn:\tclosing tcp: {0} ({1})", oSocket.RemoteEndPoint.ToString( ), se.SocketErrorCode );
}
}
if( b )
{
Utils.HandleEx( x );
}
}
#endregion
}
}
}
I omitted exception handling in Start/Stop methods for brevity. Variation in behavior is during program termination: one app shuts down almost immediately while the other gets stuck in oTcpListnr.AcceptSocket( ) call. I know that this is a blocking call, but in that case why does it not present an issue for the 1st app?
Usage of this class cannot be any simpler, e.g. for a command-line tool:
class Program
{
public static void Main( string[] args )
{
TcpServer.Start( false );
Console.Read( );
Console.WriteLine( "\r\nStopping.." );
TcpServer.Stop( );
Console.WriteLine( "\r\nStopped. Press any key to exit.." );
Console.Read( );
}
}
Whether any clients have connected or not does not make a difference, 2nd app always gets stuck.
I found a potential solution (commented lines) by checking TcpListener.Pending( ) prior to .AcceptSocket( ) call, but this immediately affects CPU utilization, therefore an inclusion of smth like Thread.Sleep(.) is a must. Altogether though I'd rather avoid this approach if possible, because of extra connection wait times and CPU utilization (small as it is).
Still, the main question is: what may cause the same exact code to execute differently? Both apps are compiled on .NET 4 Client Profile, x86 (32-bit), no specific optimizations. Thank you in advance for good ideas!
Finally found the root cause: I missed a couple of important lines [hidden in a #region] in the Stop( ) method, which starts the ball rolling. Here's how it should look:
public static void Stop( )
{
bListen= false;
if( thOutComm != null )
{
try
{
oTcpListnr.Stop( );
}
catch( Exception x )
{
Utils.HandleEx( x );
}
thOutComm.Join( iTimeout );
thOutComm= null;
}
if( oTimer != null )
{
oTimer.Change( Timeout.Infinite, Timeout.Infinite );
oTimer.Dispose( );
}
}
The call to TcpListener.Stop( ) kicks out the wait-cycle inside .AcceptSocket( ) with "A blocking operation was interrupted by a call to WSACancelBlockingCall" exception, which is then "normally ignored" (check for SocketError.Interrupted) by the code that i originally had.

Thread problem in Windows 7 Phone

Hi
I am working in windows 7 phone based app using silverlight. I have following methods in one of my UI classes, GameScreen.xaml. I am calling startTimer method in the constructor GameScreen. Problem is that when the updateTime method is called and
timeLabel.Text = "Time left: 00 : " + time;
line is executed, the program throws UnauthorizedAccessException on time variable.
private void startTimer()
{
timeThread = new Thread(new ThreadStart(startThread));
timeThread.Start();
}
public void startThread()
{
while (timeLeft > 0)
{
Thread.Sleep(1000);
updateTime();
if (timePassed % 10 == 0)
{
findNextBGResource();
changeBackgroundScene();
}
}
}
private void updateTime()
{
// update the view
String time = timeLeft.ToString();
if (timeLeft < 10)
{
time = "0" + time;
}
if (doUpdateTime && timeLeft >= 0)
{
timeLabel.Text = "Time left: 00 : " + time;
}
}
Can anyone please help me in this regard?
Best Regards...
Basically you can't modify the UI from anything other than the dispatcher thread. Two options:
Use Dispatcher.BeginInvoke to execute your ui-modifying code in the dispatcher thread
Use DispatcherTimer instead of starting a new thread and sleeping - that way the "tick" will occur in the UI thread already.
Are you sure it's on the time variable, not on timeLabel?
You can't usually edit the UI from other threads than the one that handles the UI.

Qt thread call issues

Please help me. I am struck-up with thread concept. Actually my problem : I want to display the cities List in the combobox. I am getting cities list from the webservice. I am using thread for update the combo box value after webserice call finished.
Here I can call the webservice. But I couldn't get the Reply.
I am using the following code.
MainWindow.cpp:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
CGNetwork *cgNetwork = new CGNetwork();
ui->setupUi(this);
renderThread = new RenderThread(cgNetwork);
renderThread->start();
connect(renderThread,SIGNAL(finished()),this,SLOT(initControls()));
}
void MainWindow::initControls()
{
CGMainWindowUtility *pointer = CGMainWindowUtility::instance();
QStringList cityitems;
cityitems <<tr("All");
cityitems.append(pointer->getCityList());
QStringListModel *cityModel = new QStringListModel(cityitems, this);
ui->cityComboBox->setModel(cityModel);
}
RenderThread.cpp:
RenderThread::RenderThread(CGNetwork *cgnetwork)
{
cityUrl = "http://112.138.3.181/City/Cities";
categoryUrl = "http://112.138.3.181/City/Categories";
}
void RenderThread::run()
{
qDebug()<< "THREAD Started";
CGNetwork *cgnetworks = new CGNetwork();
cgnetworks->getCityList(cityUrl);
}
CGNetwork.cpp:
void CGNetwork ::getCityList(const QUrl url)
{
cityGuideNetworkAccessManager = new QNetworkAccessManager(this);
qDebug()<<"connection";
connect(cityGuideNetworkAccessManager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(parseCityList()));
const QNetworkRequest cityRequest(url);
cityReply= cityGuideNetworkAccessManager->get(cityRequest);
connect(cityReply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError()));
}
void CGNetwork::parseCityList()
{
qDebug()<<"Parsing";
cgParser = new CGJsonParser();
cgParser->CityRead(cityReply);
}
Since QNetworkAccessManager works asynchronously, there's no need for a separate thread. You can call getCityList directly from your main thread and it won't block.
I think your slots weren't called because your QThread::run returned before any of the work its been doing had a chance to complete, since getCityList just initiated an http request without waiting for it (because QNetworkAccessManager::get doesn't block like I said above).
Also as a side note, your slots aren't getting the same parameters as their corresponding signals, I don't remember if Qt supports this.

Resources