I have the thread where the worker object is running infinite cycle. Here I have the following code that I would like it to read coordinates from list and place QGraphicsEllipseItem on these coordinates. The list can be updated by another thread, so I protect it by mutex. But sometimes the size of list may grow up so I would like to create new QGraphicsEllipse items for it if needed.
int meter_to_pixel_ratio = 20;
int x_pixel, y_pixel;
int i;
forever {
visualizationDataMutex->lock();
while(ellipseList->count()<visualizationData->count())
{
qDebug() << "Creating new visual item...";
ellipseList->append(new QGraphicsEllipseItem(0.0, 0.0, 10.0, 10.0));
ellipseList->last()->setVisible(false);
visualizationScene->addItem(ellipseList->last());
}
for(i=0; i<visualizationData->count(); i++)
{
x_pixel = meter_to_pixel_ratio*visualizationData->at(i)->x();
y_pixel = meter_to_pixel_ratio*visualizationData->at(i)->y();
ellipseList->at(i)->setPos(x_pixel, y_pixel);
ellipseList->at(i)->setBrush(QBrush(*visualizationColor->at(i)));
if(!ellipseList->at(i)->isVisible()) ellipseList->at(i)->setVisible(true);
}
visualizationDataMutex->unlock();
// repaint scene
visualizationScene->update();
QThread::msleep(100);
}
The problem I have is, that when I try to run the program I´ll obtain a runtime error. Tried to qDebug() the ellipseList->count() and seems to have the exactly same number of elements as needed (as visualizationData->count()). When commented these three lines:
//ellipseList->at(i)->setPos(x_pixel, y_pixel);
//ellipseList->at(i)->setBrush(QBrush(*visualizationColor->at(i)));
//if(!ellipseList->at(i)->isVisible()) ellipseList->at(i)->setVisible(true);
program can run without crashing. I do not understand why is this happening since there is no other function working with QGraphicsView/QGraphicsScene. (QGraphicsView was added from Qt Designer environment into mainwindow).
Related
I try to create program that takes power readings about 10 times in one second and start a new thread every second/minute to update mysql database while the main program continues taking readings. But after I use pthread_create function runs once and then program seems to exit. It is my first time trying to do something with pthread and obviously I am doing something wrong. Please help because it seems smart to use new thread to update mysql, so it will not interrupt main program. I will add my code (bit that are important I think)
the function:
void *showreadout(float readout,int l, int s) {
printf("readout: %f loops: %i sec: %i\n",readout,l,s);
return NULL;
}
and stuff from main:
pthread_t thread;
int p = 0, startminute = currentminute(),startsec,u;
float secreadout;
while (startminute == currentminute()) {
startsec = currentsec();
u = 0;
secreadout = 0;
while (startsec == currentsec()) {
secreadout += doloop(pinnumber);
u++;
}
pthread_create(&thread, NULL, showreadout(secreadout/u,u, startsec), NULL);
p++;
}
The problem was that I was trying to send variables with pthread_create() to my function and it worked once but then things seemed to go "tits up" or rather the program just stopped.
I solved it by making global variable for the readout and updated it after end of each second before calling my function with pthread_create() and using global variable in my function. I dont know is it the right way to approach it but it seems to work.
I am using a MultiThreading class which creates the required number of threads in its own threadpool and deletes itself after use.
std::thread *m_pool; //number of threads according to available cores
std::mutex m_locker;
std::condition_variable m_condition;
std::atomic<bool> m_exit;
int m_processors
m_pool = new std::thread[m_processors + 1]
void func()
{
//code
}
for (int i = 0; i < m_processors; i++)
{
m_pool[i] = std::thread(func);
}
void reset(void)
{
{
std::lock_guard<std::mutex> lock(m_locker);
m_exit = true;
}
m_condition.notify_all();
for(int i = 0; i <= m_processors; i++)
m_pool[i].join();
delete[] m_pool;
}
After running through all tasks, the for-loop is supposed to join all running threads before delete[] is being executed.
But there seems to be one last thread still running, while the m_pool does not exist anymore.
This leads to the problem, that I can't close my program anymore.
Is there any way to check if all threads are joined or wait for all threads to be joined before deleting the threadpool?
Simple typo bug I think.
Your loop that has the condition i <= m_processors is a bug and will actually process one extra entry past the end of the array. This is an off-by-one bug. Suppose m_processors is 2. You'll have an array that contains 2 elements with indices [0] and [1]. Yet, you'll be reading past the end of the array, attempting to join with the item at index [2]. m_pool[2] is undefined memory and you're likely going to either crash or block forever there.
You likely intended i < m_processors.
The real source of the problem is addressed by Wick's answer. I will extend it with some tips that also solve your problem while improving other aspects of your code.
If you use C++11 for std::thread, then you shouldn't create your thread handles using operator new[]. There are better ways of doing that with other C++ constructs, which will make everything simpler and exception safe (you don't leak memory if an unexpected exception is thrown).
Store your thread objects in a std::vector. It will manage the memory allocation and deallocation for you (no more new and delete). You can use other more flexible containers such as std::list if you insert/delete threads dynamically.
Fill the vector in place with std::generate or similar
std::vector<std::thread> m_pool;
m_pool.reserve(n_processors);
// Fill the vector
std::generate_n( std::back_inserter(m_pool), m_processors,
[](){ return std::thread(func); } );
Join all the elements using range-for loop and delete handles using container's functions.
for( std::thread& t: m_pool ) {
t.join();
}
m_pool.clear();
=======================================================
QProgressBar* pbar = new QProgressBar(this);
pbar->setMinimum(0);
pbar->setMaximum(0);
pbar->show();
for (int i = 0; i < 10000; i++) {
qDebug() << "=====flag1======";
}
pbar->close();
===========================================================
I want the ProgressBar show busy when qDebug() message, but there is no effect, the QProgressBar was blocked and close when the loop finished.
Does anyone know how to solve this problem? thank you!
Yes GUI Is Blocked, becose 10 000 it's a lot of time.
Use QThread http://doc.qt.io/qt-4.8/qthread.html .
void My_Thread::run() {
for (int i = 0; i < 1e4; i++) {
if (i % 100 == 0) {
emit UpdateProgressBar(i);
}
}
}
//In Your SLOT
void MainWindow::UpdateProgressbar(int value) {
ui->progressbar->setValue(value);
}
Main threads is locked by loop before UI appears and UI is updated right after loop ends.
If you want to see progress bar you can add QApplication::processEvents(); inside the loop. It's not the best solution but it will work.
To alow any widget to appear event loop has to be processed.
Since you have full control over main thread its event loop is not able to process events which will show and update QProgressBar.
One way to fix if, which is quick but crapy is add to your loop QApplication::processEvents(); which process evens of event loop.
Ofcaource you should also call bar->setValue(i);.
Proper way to do it is asynchronous programing which is using signals and slots. You didn't provide any details about your actual problem so can't provide good solution.
I'm currently making a Console Application game, and am working on the multiplayer version.
When I am receiving packets, I create a new thread to handle the packets, in order to return to the ReceiveFrom command as soon as possible.
The newly created thread should reprint the whole Matrix, using the new information it got regarding the changes in the matrix (it should print the Matrix with updated player positions).
The problem is, when the Print method is called on the new thread, it is badly performed. It prints the matrix very inaccurately, and many characters of the matrix are just in a mess on the Console Screen.
Here are the methods:
void Receive()
{
while (true)
{
byte[] msg = new byte[1024];
client.Receive(msg);
Thread handle = new Thread(() => HandleInput(msg));
handle.Start();
}
}
void HandleInput(byte[] msgX)
{
string data = Encoding.ASCII.GetString(msgX);
data = data.Replace("\0", "");
if (data.Contains('*') || data.Contains('\0') || data.Contains(' ')) // Move Packet (moving objects in a matrice)
{
// for example, a move packet can be: '*'!12!10
char ToMove = char.Parse(data.Split('!')[0]);
int X = int.Parse(data.Split('!')[1]);
int Y = int.Parse(data.Split('!')[2]);
grid[X, Y] = ToMove;
Print();
}
}
void Print() // print a 20x50 matrix
{
Console.Clear();
for (int y = 0; y < 52; y++)
{
Console.Write('-');
}
Console.WriteLine();
for (int i = 0; i < 20; i++)
{
Console.Write('|');
for (int j = 0; j < 50; j++)
{
Console.Write(grid[i,j]);
}
Console.WriteLine('|');
}
for (int x = 0; x < 52; x++)
{
Console.Write('-');
}
}
But, when I tried to treat the input and print the matrix on the same thread of the Receive method, it worked fine. The problem printing it only came when I printed the matrix on a separate thread.
So why does this happen? Why can't a separate thread just print the matrix correctly?
You create a new thread for every received kilobyte, but those threads are not guaranteed to start running in sequence, to wait one another, nor to finish running in sequence.
There is also no guarantee that network client will receive all needed bytes in one call of Receive method. It may happen in one, but it may happen in several calls. It may also happen that two Send methods from the other side of the connection are merged into one message. All that is guaranteed in network communication is the ordering of the bytes in the stream, and nothing else.
Your next question will probably be "so how do I make it work"? I can't do the job for you, but this is in general how I would do it:
Read chunk of bytes from the stream and store it in some buffer.
Check in the loop for existence of a complete message in the buffer. If there is such a message remove that message from the buffer, and process the message. I would process it in the same thread, and only if there are problems with that approach I would consider additional threads (or rather just one additional thread to whom I would be sending all the messages).
Repeat the loop until all complete messages are removed from the buffer, and continue reading the stream.
Just practicing my vs 2010 C++ in Windows Form Applications, I haven't done this for a very long time. I am trying to develop a simple applications where a user presses a button and then label1 begins to count everytime users presses that button1. Not sure why label1 is not incrementing by 1. Can someone tell what the problem is? Thanks in advance?
EDITED
I have found the solution and I have amended the code. I will try to close the thread and if I can't, because of I have low points, I will then try tomorrow.
namespace Counter
{
int counter = 0;
//some additional namespaces
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
counter++;
label1->Text = counter.ToString();
}
The reason why this isn't working is twofold.
The way you've written this, you only set the label text once, after you finish your "loop" (*). So the text will only change once.
Even if you move the assignment inside the loop, you're keeping the main thread busy throughout the whole function. What you want is to spawn a second thread and invoke a delegate to change the label text, something like this (C# version):
void StartCounting()
{
var thread=new Thread(()=>
{
for(int i=0;i<10;++i)
label1.Invoke((MethodInvoker)()=>{label1.Text=i.ToString();});
}
}
(*) As a side note, your entire for loop is equivalent to absolutely nothing. j will never be less than i when i starts as 0.