Executing a signal after event loop









up vote
1
down vote

favorite












In my .qml file, when a Button is pressed, it emits a signal, and some action is taken. This action takes a long time (it is encrypting data) and I want the button to "unpush" itself before this action starts, so I can show a progress bar on top.



I know Qt has event loop, and somehow, I need this signal to be emitted after this event loop , or when the GUI completes the Paint() of all objects, so the button is shown unpressed.



How is this done?



This is the code that is being executed on the signal, the heavy process is aewm_obj.save_account(key,account) , it takes 2 seconds on desktop PC and 10 seconds on Android:



function save_account() 
if (fld_password1.length===0)
if (account.type==WalletAccount.WACCT_TYPE_FULL)
return



if (fld_password1.text!==fld_password2.text)
console.log("passwords do not match")
else
btn_save.enabled=true;
if (account.type==WalletAccount.WACCT_TYPE_FULL)
key.password=fld_password1.text
account.password=fld_password1.text

btn_save.enabled=false
encrypting_message.open()
if (aewm_obj.save_account(key,account))
encrypting_message.close()
accounts_root.back_to_accounts()
else
encrypting_message.close()





The problem is, the dialog with the progress bar is shown after the heavy process finishes, however it was called before. This happens because the event loop to show and hide components is processed too late.










share|improve this question























  • Do you execute the heavy process in QML or C++?
    – eyllanesc
    Nov 8 at 21:50











  • the heavy process is in C++
    – Nulik
    Nov 8 at 21:50










  • then you must execute it in a thread
    – eyllanesc
    Nov 8 at 21:51










  • hmm, this is a bit complicated, because the user can go to another screen and that's gonna be undefined behaviour... Maybe I can call a timer few milliseconds after button has been pressed?
    – Nulik
    Nov 8 at 21:55










  • can I force a "repaint" of the screen somehow, so my "dialog" with progress bar shows before the heavy process?
    – Nulik
    Nov 8 at 22:00














up vote
1
down vote

favorite












In my .qml file, when a Button is pressed, it emits a signal, and some action is taken. This action takes a long time (it is encrypting data) and I want the button to "unpush" itself before this action starts, so I can show a progress bar on top.



I know Qt has event loop, and somehow, I need this signal to be emitted after this event loop , or when the GUI completes the Paint() of all objects, so the button is shown unpressed.



How is this done?



This is the code that is being executed on the signal, the heavy process is aewm_obj.save_account(key,account) , it takes 2 seconds on desktop PC and 10 seconds on Android:



function save_account() 
if (fld_password1.length===0)
if (account.type==WalletAccount.WACCT_TYPE_FULL)
return



if (fld_password1.text!==fld_password2.text)
console.log("passwords do not match")
else
btn_save.enabled=true;
if (account.type==WalletAccount.WACCT_TYPE_FULL)
key.password=fld_password1.text
account.password=fld_password1.text

btn_save.enabled=false
encrypting_message.open()
if (aewm_obj.save_account(key,account))
encrypting_message.close()
accounts_root.back_to_accounts()
else
encrypting_message.close()





The problem is, the dialog with the progress bar is shown after the heavy process finishes, however it was called before. This happens because the event loop to show and hide components is processed too late.










share|improve this question























  • Do you execute the heavy process in QML or C++?
    – eyllanesc
    Nov 8 at 21:50











  • the heavy process is in C++
    – Nulik
    Nov 8 at 21:50










  • then you must execute it in a thread
    – eyllanesc
    Nov 8 at 21:51










  • hmm, this is a bit complicated, because the user can go to another screen and that's gonna be undefined behaviour... Maybe I can call a timer few milliseconds after button has been pressed?
    – Nulik
    Nov 8 at 21:55










  • can I force a "repaint" of the screen somehow, so my "dialog" with progress bar shows before the heavy process?
    – Nulik
    Nov 8 at 22:00












up vote
1
down vote

favorite









up vote
1
down vote

favorite











In my .qml file, when a Button is pressed, it emits a signal, and some action is taken. This action takes a long time (it is encrypting data) and I want the button to "unpush" itself before this action starts, so I can show a progress bar on top.



I know Qt has event loop, and somehow, I need this signal to be emitted after this event loop , or when the GUI completes the Paint() of all objects, so the button is shown unpressed.



How is this done?



This is the code that is being executed on the signal, the heavy process is aewm_obj.save_account(key,account) , it takes 2 seconds on desktop PC and 10 seconds on Android:



function save_account() 
if (fld_password1.length===0)
if (account.type==WalletAccount.WACCT_TYPE_FULL)
return



if (fld_password1.text!==fld_password2.text)
console.log("passwords do not match")
else
btn_save.enabled=true;
if (account.type==WalletAccount.WACCT_TYPE_FULL)
key.password=fld_password1.text
account.password=fld_password1.text

btn_save.enabled=false
encrypting_message.open()
if (aewm_obj.save_account(key,account))
encrypting_message.close()
accounts_root.back_to_accounts()
else
encrypting_message.close()





The problem is, the dialog with the progress bar is shown after the heavy process finishes, however it was called before. This happens because the event loop to show and hide components is processed too late.










share|improve this question















In my .qml file, when a Button is pressed, it emits a signal, and some action is taken. This action takes a long time (it is encrypting data) and I want the button to "unpush" itself before this action starts, so I can show a progress bar on top.



I know Qt has event loop, and somehow, I need this signal to be emitted after this event loop , or when the GUI completes the Paint() of all objects, so the button is shown unpressed.



How is this done?



This is the code that is being executed on the signal, the heavy process is aewm_obj.save_account(key,account) , it takes 2 seconds on desktop PC and 10 seconds on Android:



function save_account() 
if (fld_password1.length===0)
if (account.type==WalletAccount.WACCT_TYPE_FULL)
return



if (fld_password1.text!==fld_password2.text)
console.log("passwords do not match")
else
btn_save.enabled=true;
if (account.type==WalletAccount.WACCT_TYPE_FULL)
key.password=fld_password1.text
account.password=fld_password1.text

btn_save.enabled=false
encrypting_message.open()
if (aewm_obj.save_account(key,account))
encrypting_message.close()
accounts_root.back_to_accounts()
else
encrypting_message.close()





The problem is, the dialog with the progress bar is shown after the heavy process finishes, however it was called before. This happens because the event loop to show and hide components is processed too late.







qt qml






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 8 at 22:04

























asked Nov 8 at 21:47









Nulik

1,59812148




1,59812148











  • Do you execute the heavy process in QML or C++?
    – eyllanesc
    Nov 8 at 21:50











  • the heavy process is in C++
    – Nulik
    Nov 8 at 21:50










  • then you must execute it in a thread
    – eyllanesc
    Nov 8 at 21:51










  • hmm, this is a bit complicated, because the user can go to another screen and that's gonna be undefined behaviour... Maybe I can call a timer few milliseconds after button has been pressed?
    – Nulik
    Nov 8 at 21:55










  • can I force a "repaint" of the screen somehow, so my "dialog" with progress bar shows before the heavy process?
    – Nulik
    Nov 8 at 22:00
















  • Do you execute the heavy process in QML or C++?
    – eyllanesc
    Nov 8 at 21:50











  • the heavy process is in C++
    – Nulik
    Nov 8 at 21:50










  • then you must execute it in a thread
    – eyllanesc
    Nov 8 at 21:51










  • hmm, this is a bit complicated, because the user can go to another screen and that's gonna be undefined behaviour... Maybe I can call a timer few milliseconds after button has been pressed?
    – Nulik
    Nov 8 at 21:55










  • can I force a "repaint" of the screen somehow, so my "dialog" with progress bar shows before the heavy process?
    – Nulik
    Nov 8 at 22:00















Do you execute the heavy process in QML or C++?
– eyllanesc
Nov 8 at 21:50





Do you execute the heavy process in QML or C++?
– eyllanesc
Nov 8 at 21:50













the heavy process is in C++
– Nulik
Nov 8 at 21:50




the heavy process is in C++
– Nulik
Nov 8 at 21:50












then you must execute it in a thread
– eyllanesc
Nov 8 at 21:51




then you must execute it in a thread
– eyllanesc
Nov 8 at 21:51












hmm, this is a bit complicated, because the user can go to another screen and that's gonna be undefined behaviour... Maybe I can call a timer few milliseconds after button has been pressed?
– Nulik
Nov 8 at 21:55




hmm, this is a bit complicated, because the user can go to another screen and that's gonna be undefined behaviour... Maybe I can call a timer few milliseconds after button has been pressed?
– Nulik
Nov 8 at 21:55












can I force a "repaint" of the screen somehow, so my "dialog" with progress bar shows before the heavy process?
– Nulik
Nov 8 at 22:00




can I force a "repaint" of the screen somehow, so my "dialog" with progress bar shows before the heavy process?
– Nulik
Nov 8 at 22:00












2 Answers
2






active

oldest

votes

















up vote
1
down vote













Use a single shot timer with a timeout of 0 to queue up an event that will be triggered after returning to the event loop. In C++ this typically looks like:



QTimer::singleShot(0, /* do something */ );


The QML equivalent is:



Timer 
interval: 0; running: true; repeat: false
onTriggered: /* do something */






share|improve this answer






















  • Maybe '0' does not work. I am using '10' for such solutions. However this answer should fix the problem.
    – sk2212
    Nov 9 at 14:11






  • 1




    @sk2212 "Maybe 0 does not work"?! There is no maybe. Using anything but 0 has larger overhead since it actually creates a system timer, when there is no need for it. All you need is a zero-duration timer, that is not really a timer but an indication that the operation is to be performed after the event queue is emptied.
    – Kuba Ober
    Nov 9 at 16:10






  • 1




    In C++, you'd not use a timer, but QMetaObject::invokeMethod( /* do something */, Qt::QueuedConnection);. In QML, Qt.callLater does that job - but c.f. QTBUG-59809!
    – Kuba Ober
    Nov 9 at 16:13







  • 1




    Well, using a QTimer::singleShot(0, ...) and doing a the invokeMethod results in exactly the same path taken. I find the 0-timer way more readable than the invoke method.
    – André
    Nov 9 at 19:46










  • actually, interval must be something like 50, running must be false. But it works nicely. Thanks
    – Nulik
    Nov 10 at 23:11

















up vote
-1
down vote













After reading this article: https://doc.qt.io/archives/qq/qq27-responsive-guis.html



I have added code to my C++ function to process all the events before it starts the heavy process. This way, I empty event queue and the GUI updates automatically showing the progress bar dialog. (a sort of repaint() of all QML objects)



for (int i=0; i<10000; i++) 
QCoreApplication::sendPostedEvents();
QCoreApplication::processEvents();



The delay caused by this loop is unnoticeable compared to the 2 seconds of processing time. The 10,000 iterations are needed on Android, on desktop 10 iterations is enough. Using small amount of iterations, will show the dialog not at full opacity, due to fade effects.






share|improve this answer




















  • This seems bad design and not very flexible. Why not use a worker thread and a progress bar? You can disable UI interaction during that time but the UI stays responsive with updates.
    – Jan Win
    Nov 9 at 9:35






  • 1




    The processEvents call exposes your entire codebase to reentrancy, and I bet that you didn't design your code with reentrancy in mind. Don't do that.
    – Kuba Ober
    Nov 9 at 16:15










  • reentrancy is when it is interruped by hadware interrupt (or soft interrupt), here, it is not reentrancy, since I am interrupting it in a safe place. During this interrupt the local stack is not being changed, process objects are not being changed. global vars may be changed, but that's why they are global vars. It is just quick patch for the problem, I will rewrite it in the future with a timer on QML side.
    – Nulik
    Nov 9 at 18:55










  • No. Reentrancy means that a function not designed to do so is on the call stack two or more times in a given thread. And processEvents can end up calling any method in your code that would be callable as a result of event processing, I.e. timers, UI interaction including windows getting closed, communications – heck, you might start doing application-exit cleanup tasks within that processEvents. And you simply should not block the event loop period. Do your computation asynchronously. It’s amenable to it. Use the concurrent pramework of standard C++ async primitives.
    – Kuba Ober
    Nov 12 at 12:47











  • Interrupt handling can cause reentrancy, but is hardly the only way of it happening. Recall that on Windows, event processing can invoke IO completion as well, so both Qt and the OS itself may invoke code you never designed to be invoked.
    – Kuba Ober
    Nov 12 at 12:51











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53216647%2fexecuting-a-signal-after-event-loop%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote













Use a single shot timer with a timeout of 0 to queue up an event that will be triggered after returning to the event loop. In C++ this typically looks like:



QTimer::singleShot(0, /* do something */ );


The QML equivalent is:



Timer 
interval: 0; running: true; repeat: false
onTriggered: /* do something */






share|improve this answer






















  • Maybe '0' does not work. I am using '10' for such solutions. However this answer should fix the problem.
    – sk2212
    Nov 9 at 14:11






  • 1




    @sk2212 "Maybe 0 does not work"?! There is no maybe. Using anything but 0 has larger overhead since it actually creates a system timer, when there is no need for it. All you need is a zero-duration timer, that is not really a timer but an indication that the operation is to be performed after the event queue is emptied.
    – Kuba Ober
    Nov 9 at 16:10






  • 1




    In C++, you'd not use a timer, but QMetaObject::invokeMethod( /* do something */, Qt::QueuedConnection);. In QML, Qt.callLater does that job - but c.f. QTBUG-59809!
    – Kuba Ober
    Nov 9 at 16:13







  • 1




    Well, using a QTimer::singleShot(0, ...) and doing a the invokeMethod results in exactly the same path taken. I find the 0-timer way more readable than the invoke method.
    – André
    Nov 9 at 19:46










  • actually, interval must be something like 50, running must be false. But it works nicely. Thanks
    – Nulik
    Nov 10 at 23:11














up vote
1
down vote













Use a single shot timer with a timeout of 0 to queue up an event that will be triggered after returning to the event loop. In C++ this typically looks like:



QTimer::singleShot(0, /* do something */ );


The QML equivalent is:



Timer 
interval: 0; running: true; repeat: false
onTriggered: /* do something */






share|improve this answer






















  • Maybe '0' does not work. I am using '10' for such solutions. However this answer should fix the problem.
    – sk2212
    Nov 9 at 14:11






  • 1




    @sk2212 "Maybe 0 does not work"?! There is no maybe. Using anything but 0 has larger overhead since it actually creates a system timer, when there is no need for it. All you need is a zero-duration timer, that is not really a timer but an indication that the operation is to be performed after the event queue is emptied.
    – Kuba Ober
    Nov 9 at 16:10






  • 1




    In C++, you'd not use a timer, but QMetaObject::invokeMethod( /* do something */, Qt::QueuedConnection);. In QML, Qt.callLater does that job - but c.f. QTBUG-59809!
    – Kuba Ober
    Nov 9 at 16:13







  • 1




    Well, using a QTimer::singleShot(0, ...) and doing a the invokeMethod results in exactly the same path taken. I find the 0-timer way more readable than the invoke method.
    – André
    Nov 9 at 19:46










  • actually, interval must be something like 50, running must be false. But it works nicely. Thanks
    – Nulik
    Nov 10 at 23:11












up vote
1
down vote










up vote
1
down vote









Use a single shot timer with a timeout of 0 to queue up an event that will be triggered after returning to the event loop. In C++ this typically looks like:



QTimer::singleShot(0, /* do something */ );


The QML equivalent is:



Timer 
interval: 0; running: true; repeat: false
onTriggered: /* do something */






share|improve this answer














Use a single shot timer with a timeout of 0 to queue up an event that will be triggered after returning to the event loop. In C++ this typically looks like:



QTimer::singleShot(0, /* do something */ );


The QML equivalent is:



Timer 
interval: 0; running: true; repeat: false
onTriggered: /* do something */







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 9 at 20:13

























answered Nov 9 at 2:44









Jason Haslam

1,203513




1,203513











  • Maybe '0' does not work. I am using '10' for such solutions. However this answer should fix the problem.
    – sk2212
    Nov 9 at 14:11






  • 1




    @sk2212 "Maybe 0 does not work"?! There is no maybe. Using anything but 0 has larger overhead since it actually creates a system timer, when there is no need for it. All you need is a zero-duration timer, that is not really a timer but an indication that the operation is to be performed after the event queue is emptied.
    – Kuba Ober
    Nov 9 at 16:10






  • 1




    In C++, you'd not use a timer, but QMetaObject::invokeMethod( /* do something */, Qt::QueuedConnection);. In QML, Qt.callLater does that job - but c.f. QTBUG-59809!
    – Kuba Ober
    Nov 9 at 16:13







  • 1




    Well, using a QTimer::singleShot(0, ...) and doing a the invokeMethod results in exactly the same path taken. I find the 0-timer way more readable than the invoke method.
    – André
    Nov 9 at 19:46










  • actually, interval must be something like 50, running must be false. But it works nicely. Thanks
    – Nulik
    Nov 10 at 23:11
















  • Maybe '0' does not work. I am using '10' for such solutions. However this answer should fix the problem.
    – sk2212
    Nov 9 at 14:11






  • 1




    @sk2212 "Maybe 0 does not work"?! There is no maybe. Using anything but 0 has larger overhead since it actually creates a system timer, when there is no need for it. All you need is a zero-duration timer, that is not really a timer but an indication that the operation is to be performed after the event queue is emptied.
    – Kuba Ober
    Nov 9 at 16:10






  • 1




    In C++, you'd not use a timer, but QMetaObject::invokeMethod( /* do something */, Qt::QueuedConnection);. In QML, Qt.callLater does that job - but c.f. QTBUG-59809!
    – Kuba Ober
    Nov 9 at 16:13







  • 1




    Well, using a QTimer::singleShot(0, ...) and doing a the invokeMethod results in exactly the same path taken. I find the 0-timer way more readable than the invoke method.
    – André
    Nov 9 at 19:46










  • actually, interval must be something like 50, running must be false. But it works nicely. Thanks
    – Nulik
    Nov 10 at 23:11















Maybe '0' does not work. I am using '10' for such solutions. However this answer should fix the problem.
– sk2212
Nov 9 at 14:11




Maybe '0' does not work. I am using '10' for such solutions. However this answer should fix the problem.
– sk2212
Nov 9 at 14:11




1




1




@sk2212 "Maybe 0 does not work"?! There is no maybe. Using anything but 0 has larger overhead since it actually creates a system timer, when there is no need for it. All you need is a zero-duration timer, that is not really a timer but an indication that the operation is to be performed after the event queue is emptied.
– Kuba Ober
Nov 9 at 16:10




@sk2212 "Maybe 0 does not work"?! There is no maybe. Using anything but 0 has larger overhead since it actually creates a system timer, when there is no need for it. All you need is a zero-duration timer, that is not really a timer but an indication that the operation is to be performed after the event queue is emptied.
– Kuba Ober
Nov 9 at 16:10




1




1




In C++, you'd not use a timer, but QMetaObject::invokeMethod( /* do something */, Qt::QueuedConnection);. In QML, Qt.callLater does that job - but c.f. QTBUG-59809!
– Kuba Ober
Nov 9 at 16:13





In C++, you'd not use a timer, but QMetaObject::invokeMethod( /* do something */, Qt::QueuedConnection);. In QML, Qt.callLater does that job - but c.f. QTBUG-59809!
– Kuba Ober
Nov 9 at 16:13





1




1




Well, using a QTimer::singleShot(0, ...) and doing a the invokeMethod results in exactly the same path taken. I find the 0-timer way more readable than the invoke method.
– André
Nov 9 at 19:46




Well, using a QTimer::singleShot(0, ...) and doing a the invokeMethod results in exactly the same path taken. I find the 0-timer way more readable than the invoke method.
– André
Nov 9 at 19:46












actually, interval must be something like 50, running must be false. But it works nicely. Thanks
– Nulik
Nov 10 at 23:11




actually, interval must be something like 50, running must be false. But it works nicely. Thanks
– Nulik
Nov 10 at 23:11












up vote
-1
down vote













After reading this article: https://doc.qt.io/archives/qq/qq27-responsive-guis.html



I have added code to my C++ function to process all the events before it starts the heavy process. This way, I empty event queue and the GUI updates automatically showing the progress bar dialog. (a sort of repaint() of all QML objects)



for (int i=0; i<10000; i++) 
QCoreApplication::sendPostedEvents();
QCoreApplication::processEvents();



The delay caused by this loop is unnoticeable compared to the 2 seconds of processing time. The 10,000 iterations are needed on Android, on desktop 10 iterations is enough. Using small amount of iterations, will show the dialog not at full opacity, due to fade effects.






share|improve this answer




















  • This seems bad design and not very flexible. Why not use a worker thread and a progress bar? You can disable UI interaction during that time but the UI stays responsive with updates.
    – Jan Win
    Nov 9 at 9:35






  • 1




    The processEvents call exposes your entire codebase to reentrancy, and I bet that you didn't design your code with reentrancy in mind. Don't do that.
    – Kuba Ober
    Nov 9 at 16:15










  • reentrancy is when it is interruped by hadware interrupt (or soft interrupt), here, it is not reentrancy, since I am interrupting it in a safe place. During this interrupt the local stack is not being changed, process objects are not being changed. global vars may be changed, but that's why they are global vars. It is just quick patch for the problem, I will rewrite it in the future with a timer on QML side.
    – Nulik
    Nov 9 at 18:55










  • No. Reentrancy means that a function not designed to do so is on the call stack two or more times in a given thread. And processEvents can end up calling any method in your code that would be callable as a result of event processing, I.e. timers, UI interaction including windows getting closed, communications – heck, you might start doing application-exit cleanup tasks within that processEvents. And you simply should not block the event loop period. Do your computation asynchronously. It’s amenable to it. Use the concurrent pramework of standard C++ async primitives.
    – Kuba Ober
    Nov 12 at 12:47











  • Interrupt handling can cause reentrancy, but is hardly the only way of it happening. Recall that on Windows, event processing can invoke IO completion as well, so both Qt and the OS itself may invoke code you never designed to be invoked.
    – Kuba Ober
    Nov 12 at 12:51















up vote
-1
down vote













After reading this article: https://doc.qt.io/archives/qq/qq27-responsive-guis.html



I have added code to my C++ function to process all the events before it starts the heavy process. This way, I empty event queue and the GUI updates automatically showing the progress bar dialog. (a sort of repaint() of all QML objects)



for (int i=0; i<10000; i++) 
QCoreApplication::sendPostedEvents();
QCoreApplication::processEvents();



The delay caused by this loop is unnoticeable compared to the 2 seconds of processing time. The 10,000 iterations are needed on Android, on desktop 10 iterations is enough. Using small amount of iterations, will show the dialog not at full opacity, due to fade effects.






share|improve this answer




















  • This seems bad design and not very flexible. Why not use a worker thread and a progress bar? You can disable UI interaction during that time but the UI stays responsive with updates.
    – Jan Win
    Nov 9 at 9:35






  • 1




    The processEvents call exposes your entire codebase to reentrancy, and I bet that you didn't design your code with reentrancy in mind. Don't do that.
    – Kuba Ober
    Nov 9 at 16:15










  • reentrancy is when it is interruped by hadware interrupt (or soft interrupt), here, it is not reentrancy, since I am interrupting it in a safe place. During this interrupt the local stack is not being changed, process objects are not being changed. global vars may be changed, but that's why they are global vars. It is just quick patch for the problem, I will rewrite it in the future with a timer on QML side.
    – Nulik
    Nov 9 at 18:55










  • No. Reentrancy means that a function not designed to do so is on the call stack two or more times in a given thread. And processEvents can end up calling any method in your code that would be callable as a result of event processing, I.e. timers, UI interaction including windows getting closed, communications – heck, you might start doing application-exit cleanup tasks within that processEvents. And you simply should not block the event loop period. Do your computation asynchronously. It’s amenable to it. Use the concurrent pramework of standard C++ async primitives.
    – Kuba Ober
    Nov 12 at 12:47











  • Interrupt handling can cause reentrancy, but is hardly the only way of it happening. Recall that on Windows, event processing can invoke IO completion as well, so both Qt and the OS itself may invoke code you never designed to be invoked.
    – Kuba Ober
    Nov 12 at 12:51













up vote
-1
down vote










up vote
-1
down vote









After reading this article: https://doc.qt.io/archives/qq/qq27-responsive-guis.html



I have added code to my C++ function to process all the events before it starts the heavy process. This way, I empty event queue and the GUI updates automatically showing the progress bar dialog. (a sort of repaint() of all QML objects)



for (int i=0; i<10000; i++) 
QCoreApplication::sendPostedEvents();
QCoreApplication::processEvents();



The delay caused by this loop is unnoticeable compared to the 2 seconds of processing time. The 10,000 iterations are needed on Android, on desktop 10 iterations is enough. Using small amount of iterations, will show the dialog not at full opacity, due to fade effects.






share|improve this answer












After reading this article: https://doc.qt.io/archives/qq/qq27-responsive-guis.html



I have added code to my C++ function to process all the events before it starts the heavy process. This way, I empty event queue and the GUI updates automatically showing the progress bar dialog. (a sort of repaint() of all QML objects)



for (int i=0; i<10000; i++) 
QCoreApplication::sendPostedEvents();
QCoreApplication::processEvents();



The delay caused by this loop is unnoticeable compared to the 2 seconds of processing time. The 10,000 iterations are needed on Android, on desktop 10 iterations is enough. Using small amount of iterations, will show the dialog not at full opacity, due to fade effects.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 8 at 23:33









Nulik

1,59812148




1,59812148











  • This seems bad design and not very flexible. Why not use a worker thread and a progress bar? You can disable UI interaction during that time but the UI stays responsive with updates.
    – Jan Win
    Nov 9 at 9:35






  • 1




    The processEvents call exposes your entire codebase to reentrancy, and I bet that you didn't design your code with reentrancy in mind. Don't do that.
    – Kuba Ober
    Nov 9 at 16:15










  • reentrancy is when it is interruped by hadware interrupt (or soft interrupt), here, it is not reentrancy, since I am interrupting it in a safe place. During this interrupt the local stack is not being changed, process objects are not being changed. global vars may be changed, but that's why they are global vars. It is just quick patch for the problem, I will rewrite it in the future with a timer on QML side.
    – Nulik
    Nov 9 at 18:55










  • No. Reentrancy means that a function not designed to do so is on the call stack two or more times in a given thread. And processEvents can end up calling any method in your code that would be callable as a result of event processing, I.e. timers, UI interaction including windows getting closed, communications – heck, you might start doing application-exit cleanup tasks within that processEvents. And you simply should not block the event loop period. Do your computation asynchronously. It’s amenable to it. Use the concurrent pramework of standard C++ async primitives.
    – Kuba Ober
    Nov 12 at 12:47











  • Interrupt handling can cause reentrancy, but is hardly the only way of it happening. Recall that on Windows, event processing can invoke IO completion as well, so both Qt and the OS itself may invoke code you never designed to be invoked.
    – Kuba Ober
    Nov 12 at 12:51

















  • This seems bad design and not very flexible. Why not use a worker thread and a progress bar? You can disable UI interaction during that time but the UI stays responsive with updates.
    – Jan Win
    Nov 9 at 9:35






  • 1




    The processEvents call exposes your entire codebase to reentrancy, and I bet that you didn't design your code with reentrancy in mind. Don't do that.
    – Kuba Ober
    Nov 9 at 16:15










  • reentrancy is when it is interruped by hadware interrupt (or soft interrupt), here, it is not reentrancy, since I am interrupting it in a safe place. During this interrupt the local stack is not being changed, process objects are not being changed. global vars may be changed, but that's why they are global vars. It is just quick patch for the problem, I will rewrite it in the future with a timer on QML side.
    – Nulik
    Nov 9 at 18:55










  • No. Reentrancy means that a function not designed to do so is on the call stack two or more times in a given thread. And processEvents can end up calling any method in your code that would be callable as a result of event processing, I.e. timers, UI interaction including windows getting closed, communications – heck, you might start doing application-exit cleanup tasks within that processEvents. And you simply should not block the event loop period. Do your computation asynchronously. It’s amenable to it. Use the concurrent pramework of standard C++ async primitives.
    – Kuba Ober
    Nov 12 at 12:47











  • Interrupt handling can cause reentrancy, but is hardly the only way of it happening. Recall that on Windows, event processing can invoke IO completion as well, so both Qt and the OS itself may invoke code you never designed to be invoked.
    – Kuba Ober
    Nov 12 at 12:51
















This seems bad design and not very flexible. Why not use a worker thread and a progress bar? You can disable UI interaction during that time but the UI stays responsive with updates.
– Jan Win
Nov 9 at 9:35




This seems bad design and not very flexible. Why not use a worker thread and a progress bar? You can disable UI interaction during that time but the UI stays responsive with updates.
– Jan Win
Nov 9 at 9:35




1




1




The processEvents call exposes your entire codebase to reentrancy, and I bet that you didn't design your code with reentrancy in mind. Don't do that.
– Kuba Ober
Nov 9 at 16:15




The processEvents call exposes your entire codebase to reentrancy, and I bet that you didn't design your code with reentrancy in mind. Don't do that.
– Kuba Ober
Nov 9 at 16:15












reentrancy is when it is interruped by hadware interrupt (or soft interrupt), here, it is not reentrancy, since I am interrupting it in a safe place. During this interrupt the local stack is not being changed, process objects are not being changed. global vars may be changed, but that's why they are global vars. It is just quick patch for the problem, I will rewrite it in the future with a timer on QML side.
– Nulik
Nov 9 at 18:55




reentrancy is when it is interruped by hadware interrupt (or soft interrupt), here, it is not reentrancy, since I am interrupting it in a safe place. During this interrupt the local stack is not being changed, process objects are not being changed. global vars may be changed, but that's why they are global vars. It is just quick patch for the problem, I will rewrite it in the future with a timer on QML side.
– Nulik
Nov 9 at 18:55












No. Reentrancy means that a function not designed to do so is on the call stack two or more times in a given thread. And processEvents can end up calling any method in your code that would be callable as a result of event processing, I.e. timers, UI interaction including windows getting closed, communications – heck, you might start doing application-exit cleanup tasks within that processEvents. And you simply should not block the event loop period. Do your computation asynchronously. It’s amenable to it. Use the concurrent pramework of standard C++ async primitives.
– Kuba Ober
Nov 12 at 12:47





No. Reentrancy means that a function not designed to do so is on the call stack two or more times in a given thread. And processEvents can end up calling any method in your code that would be callable as a result of event processing, I.e. timers, UI interaction including windows getting closed, communications – heck, you might start doing application-exit cleanup tasks within that processEvents. And you simply should not block the event loop period. Do your computation asynchronously. It’s amenable to it. Use the concurrent pramework of standard C++ async primitives.
– Kuba Ober
Nov 12 at 12:47













Interrupt handling can cause reentrancy, but is hardly the only way of it happening. Recall that on Windows, event processing can invoke IO completion as well, so both Qt and the OS itself may invoke code you never designed to be invoked.
– Kuba Ober
Nov 12 at 12:51





Interrupt handling can cause reentrancy, but is hardly the only way of it happening. Recall that on Windows, event processing can invoke IO completion as well, so both Qt and the OS itself may invoke code you never designed to be invoked.
– Kuba Ober
Nov 12 at 12:51


















 

draft saved


draft discarded















































 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53216647%2fexecuting-a-signal-after-event-loop%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Use pre created SQLite database for Android project in kotlin

Darth Vader #20

Ondo