Thread.sleep activates before previoues code - multithreading

This code will check if three buttons in a row have the same text. If it does, it will change color to green on those buttons and change int counter to 9. When it is past this piece of code, it will reset all buttons their original state because counter == 9.
Problem is, it will sleep before it makes the buttons green. Why is that?
int counter = 0;
private void winCheck(String sign)
{
if (jButton1.getText().equals(sign))
{
if (jButton2.getText().equals(sign))
{
if (jButton3.getText().equals(sign))
{
jButton1.setBackground(Color.GREEN);
jButton2.setBackground(Color.GREEN);
jButton3.setBackground(Color.GREEN);
counter = 9;
}
try {
Thread.sleep(1000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}
}
// This last part to show what I mean with reset.
counter++;
if (counter == 10)
{
jButton1.setBackground(null);
jButton1.setText(" ");
counter = 0;
}

Answer by Kirill Shlenskiy (please upvote his comments):
Problem is, it will sleep before it makes the buttons green" - that is unlikely to be true. Step through your code - I bet that the button background colour value will be exactly what you expect it to be right after you set it (and before you hit Thread.sleep). You just can't see the update because your UI thread is busy waiting on the blocking Thread.sleep call to finish and not pumping. You either need an asynchronous alternative to sleep (timer for example) or a way to force the UI element to redraw immediately. – Kirill Shlenskiy Jul 10 at 13:38
I set the colour to be green but it is not drawn before I put the thread to sleep? – uranibaba Jul 11 at 8:10
#uranibaba, correct. And that's by design. The UI thread redraws the UI when it has nothing else to do. Thread.sleep does not defer the rest of the method - it blocks the thread so that it can't do anything else (i.e. redraw the UI) until the synchronous work is complete. – Kirill Shlenskiy Jul 11 at 10:43

Related

QProgressBar blocked by main Thread?

=======================================================
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.

Qt5: How to execute a "task" based on a weekly scheduler?

I am using Qt5 on Windows7 platform.
I have an app running 24/24, that it's supposed to connect to some remote devices in order to open or close the service on them. Connection is done via TCP.
For each day of the week there is/should be the possibility to set the hour&minute for both operations/tasks: open-service and close-service, as in the code below:
#define SUNDAY 0
#define MONDAY 1
//...
#define SATURDAY 6
struct Day_OpenCloseService
{
bool automaticOpenService;
int openHour;
int openMinute;
bool automaticCloseService;
int closeHour;
int closeMinute;
};
QVector<Day_OpenCloseService> Week_OpenCloseService(7);
Week_OpenCloseService[SUNDAY].automaticOpenService = true;
Week_OpenCloseService[SUNDAY].openHour = 7;
Week_OpenCloseService[SUNDAY].openMinute = 0;
Week_OpenCloseService[SUNDAY].automaticCloseService = false;
//
Week_OpenCloseService[MONDAY].automaticOpenService = true;
Week_OpenCloseService[MONDAY].openHour = 4;
Week_OpenCloseService[MONDAY].openMinute = 30;
Week_OpenCloseService[MONDAY].automaticCloseService = true;
Week_OpenCloseService[MONDAY].closeHour = 23;
Week_OpenCloseService[MONDAY].closeMinute = 0;
// ...
Week_OpenCloseService[SATURDAY].automaticOpenService = true;
Week_OpenCloseService[SATURDAY].openHour = 6;
Week_OpenCloseService[SATURDAY].openMinute = 15;
Week_OpenCloseService[SATURDAY].automaticCloseService = false;
Week_OpenCloseService[SATURDAY].closeHour = 23;
Week_OpenCloseService[SATURDAY].closeMinute = 59;
If automaticOpenService is true for a day, then an open-service will be executed at the specified hour&minute, in a new thread (I suppose).
If automaticOpenService is false, then no open-service is executed for that day of the week.
And the same goes for the automaticCloseService...
Now, the question is:
How to start the open-service and close-service tasks, based on the above "scheduler"?
Ok, the open-service and close-service tasks are not implemented yet, but they will be just some simple commands via TCP connection to the remote devices (which are listening on a certain port).
I'm still weighing on how to implement that, too... (single-thread, multi-thread, concurrent, etc).
A basic implementation of a scheduler will hold a list of upcoming tasks (maybe with just two items in the list in your case) that is kept sorted by the time at which those tasks need to be executed. Since you are using Qt, you could use QDateTime objects to represent the times at which your upcoming tasks need to be done.
Once you have that list set up, it's just a matter of calculating how many seconds remain between the current time and the timestamp of the first item in the list, and then waiting that number of seconds. The QDateTime::secsTo() method is very useful here as it will do just that calculation for you. You can then call QTimer::singleShot() to make it so that a signal will be emitted in that-many seconds.
When the qTimer's signal is emitted and your slot-method is called, you slot method will check the QDateTime of the first item in the list; if the current time is greater than or equal to that item's QDateTime, then it's time to execute the task, and the pop that item off the head of the list (and maybe reschedule a new task for tomorrow?). Repeat until either the list is empty or the first item in the list has a QDateTime that is still in the future, in which case you'd go back to step 1 again. Repeat indefinitely.
Note that multithreading isn't required to accomplish this task under Qt (and using multithreading wouldn't make the task any easier, either, so I'd avoid it if possible).

Atomic compare exchange. Is it correct?

I want to atomically add 1 to a counter under certain conditions, but I'm not sure if following is correct in a threaded environment:
void UpdateCounterAndLastSessionIfMoreThan60Seconds() const {
auto currentTime = timeProvider->GetCurrentTime();
auto currentLastSession = lastSession.load();
bool shouldIncrement = (currentTime - currentLastSession >= 1 * 60);
if (shouldIncrement) {
auto isUpdate = lastSession.compare_exchange_strong(currentLastSession, currentTime);
if (isUpdate)
changes.fetch_add(1);
}
}
private:
std::shared_ptr<Time> timeProvider;
mutable std::atomic<time_t> lastSession;
mutable std::atomic<uint32_t> changes;
I don't want to increment changes multiple times if 2 threads simultaneously evaluate to shouldIncrement = true and isUpdate = true also (only one should increment changes in that case)
I'm no C++ expert, but it looks to me like you've got a race condition between the evaluation of "isUpdate" and the call to "fetch_add(1)".
So I think the answer to your question "Is this thread safe?" is "No, it is not".
It is at least a bit iffy, as following scenario will show:
First thread 1 does these:
auto currentTime = timeProvider->GetCurrentTime();
auto currentLastSession = lastSession.load();
bool shouldIncrement = (currentTime - currentLastSession >= 1 * 60);
Then thread 2 does the same 3 statements, but so that currentTime is more than it just was for Thread 1.
Then thread 1 continues to update lastSession with it's time, which is less than thread 2's time.
Then thread 2 gets its turn, but fails to update lastSession, because thread 1 changed the value already.
So end result is, lastSession is outdated, because thread 2 failed to update it to the latest value. This might not matter in all cases, situation might be fixed very soon after, but it's one ugly corner which might break some assumptions somewhere, if not with current code then after some later changes.
Another thing to note is, lastSession and chnages are not atomically in sync. Other threads occasionally see changed lastSession with changes counter still not incremeted for that change. Again this is something which might not matter, but it's easy to forget something like this and accidentally code something which assumes they are in sync.
I'm not immediately sure if you can make this 100% safe with just atomics. Wrap it in a mutex instead.

Multi-threaded programming - Producer Consumer

The pseudocode for a 'Inadequate implementation' of a producer consumer problem mentioned in wikipedia is as below. This solution is said to have a race condition which could cause deadlock.
My question is : Wouldn't just modifying the conditions of wakeing up the other thread as below solve the possible deadlock issue. That way there is not just one wakeup which could be lost, but subsequent multiple ones, or am I missing something. Trying to understand here.
int itemCount = 0;
procedure producer() {
while (true) {
item = produceItem();
if (itemCount == BUFFER_SIZE) {
sleep();
}
putItemIntoBuffer(item);
itemCount = itemCount + 1;
//if (itemCount == 1) <<<<<<<< change this to below condition
if(itemCount > 0)
{
wakeup(consumer);
}
}
}
procedure consumer() {
while (true) {
if (itemCount == 0) {
sleep();
}
item = removeItemFromBuffer();
itemCount = itemCount - 1;
//if (itemCount == BUFFER_SIZE - 1) <<<<<<< Change this to below
if(itermCount < BUFFER_SIZE)
{
wakeup(producer);
}
consumeItem(item);
}
}
Wouldn't just modifying the conditions of wakeing up the other thread as below solve the possible deadlock issue.
No, the race condition still exists. The problem is that there are multiple threads doing the consuming and/or producing. When a consumer (for example) is awoken and told that there are items to be processed, it might go remove the item but some other thread (or threads) has gotten there before it.
The solution is to do the following:
lock() {
while (itemCount == 0) {
sleep();
}
item = removeItemFromBuffer();
itemCount = itemCount - 1;
}
So even if the consumer is awoken, it immediately checks again that the itemCount is not 0 with a while loop. Even though the itemCount was incremented, another thread might have removed that element and decremented itemCount before the thread that got the signal had a chance to act. That is the race.
It is the same for the producer side although the race is to stop the producer from over-filling the buffer. A producer may be awoken because there is space available but by the time it goes to put items into buffer, other threads have beaten it and re-filled the buffer. It has to test again to make sure after it was awoken that there is space.
I go into line by line detail about this race on this page from my website entitled Producer Consumer Thread Race Conditions. There also is a little test program there that demonstrates the issue.
The important point to realize is that in most locking implementations, there is a queue of threads waiting to gain access to a lock. When a signal is sent to a thread, it first has to reacquire the lock, before it can continue. When a thread is signaled it then goes to the end of the BLOCK queue. If there are additional threads that are waiting for the lock but not waiting, they will run ahead of the awoken thread and steal the items.
This is very similar to this question about while loops in similar code. Unfortunately the accepted answer does not address this race condition. Please consider upvoting my answer to a similar question here. Spurious wakeups are an issue but the real problem here is the race condition wikipedia is talking about.

simple counter in windows forms application C++

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.

Resources