MFC: Update Ribbon Bar elements to reflect operation progress - multithreading

I am making a simulation tool, that runs simulation (in a separate thread) over user defined number of iterations, which can be entered in an Edit control on the Ribbon Bar. I would like to reuse it to show current iteration during simulation. I also also put CMFCRibbonProgressBar to show the progress. The Ribbon Bar is created with resource editor.
The question is what is the what to get the progress bar and iteration counter to get timely updated without causing the GUI to become unresponsive?
The conventional way over ON_UPDATE_COMMAND_UI routines requires activity in the window, like moving the mouse.
So I probably need a thread that would update this controls. Things like simply creating a thread and trying to update the controls from or using concurrency::parallel_invoke are not suitable.The former simply doesn't work, the latter works, but causes GUI to freeze.
I store pointers in my document to simplify access to the controls. https://stackoverflow.com/a/25429446?noredirect=1
My general idea is (pseudocode)
beginUpdatingThread()
{
while(simulating)
{
updateEditControl();
updateProgressBar();
sleep_40_ms();//conserves the resorces as there is no sense to update more frequent than 25 times per second
}
}
What is correct way of implementing this?

ASSERT(m_hWnd!=NULL);
MSG msg;
while (simulating)
{
// Handle dialog messages
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(!IsDialogMessage(&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}

I solved this by adding a method to the main window that performs the update. now the thread updating from above continually post messages to the main window to perform the update:
auto h = static_cast<CMainFrame*>(AfxGetMainWnd())->m_hWnd;
//here code for starting simulation in a separate thread
std::thread updating([this,h]{
while (simulating)
{
::PostMessage(h, WM_UPDATE_VISUALS, sumulator.getCurrentIteration(), 0);
std::this_thread::sleep_for(std::chrono::milliseconds(40));
}
::PostMessage(h, WM_UPDATE_VISUALS, num_iterations, 0);
});
updating.detach()
I made a subtle mistake at first by capturing h by reference, which quickly expires
But in the end, the above code does exactly what I wanted to achieve

Related

Call fabricjs event continuously

I'm calling custom event in this way:
How can I fire custom events on canvas in Fabric JS?
Is there a way to call it continuously like the object:scaling/moving events?
SOLUTION:
I solved this problem using the object:moving event:
canvas.on({'object:moving': handleMovement});
...
var handleMovement = function (event) {
//only when a specific corner was dragged
if (event.target.__corner == 'mb') {
//reset original position
event.target.top = event.target.originalState.top;
event.target.left = event.target.originalState.left;
//do other stuff
}
}
If you need to call the event continuously, you could wrap it in a while loop, or use some sort of timeout.
while (shouldFire) {
canvas.trigger(event);
}
or
setTimeout(triggerEvent, 100);
function triggerEvent() {
canvas.trigger(event);
setTimeout(triggerEvent, 100);
}
However, that might not be ideal for the user (especially the while).
While the object:scaling/moving events may appear to be called continuously, I believe they are simply being called incredibly rapidly in response to user interaction. There's a good event demo on the fabricjs website for looking at this. If you select an object and simply hold it stationary, there are no events fired by the canvas. Instead, the events are only fired in response to user movement, such as dragging the shape around the canvas. So, instead of trying to make the events continuously fired, you could simply listen for small changes in the user's input.

RobotC: Multithreading in TeleOp (controlling mode)

I am making a program for a robot in a competition, and need to multithread.
When I make a second task (task two()) and try to start (startTask) it with a button press from a controller, it just executes the first statement of the task and only as long as the button is pressed, instead of the whole block. I've tried many things including putting a loop in the second task also, using a function instead of a task and sleeping for 200 milliseconds before, and after the startTask(two); function, but the same thing happens every time.
I can't post my program because I don't want other people to steal it, sorry.
What edits will make it run the whole block?
Any help would be appreciated.
Since this is Controller Mode, I'm assuming that you are setting the motors to stop when the corresponding button is not pressed.
if([...])
[...]
else
{
setMotorSpeed(motor10, 0);
}
This is the cause for the stopping of the motors when you release. All of the other methods that you tried had nothing to do with this, so they shouldn't have worked.
You need to put something like this:
int Motor10Speed;
[...]
if([...])
[...]
else
{
setMotorSpeed(motor10, Motor10Speed);
}
This will control an individual motor. Repeat this for all other motors being used.
After that is done, make the function look something like this:
task mini_function();
task main()
{
[...]
}
task mini_function()
{
Motor10Speed = 50;
sleep(1000);
Motor10Speed = 0;
}
Expand the above program so it matches your current function, while using the MotorSpeed variables as setMotorSpeed variables.
This should make you able to drive and run a function at the same time without them interrupting each other.

Linux x11 XGrabKeyboard() cause keyboard to be frozen

I am writing a program which need to listen the user keyboard stroks.
I use function XGrabKeyboard() and this is my code:
XGrabKeyboard(pDisplay, DefaultRootWindow(pDisplay), True, GrabModeAsync, GrabModeAsync, CurrentTime);
XEvent event;
while (true)
{
XNextEvent(pDisplay, &event);
switch (event.type)
{
...
}
}
But it causes the keyboard and cursor to be frozen.
I looked up the man page, it only says: "The third parameter specifies a Boolean value that indicates whether the keyboard events are to be reported as usual."
I tried both true or false or the 3rd param, both GrabModeAsync and GrabModeSync for the 4th and 5th param, but it doesn't work.
After calling XGrabKeyboard(), the keyboard is frozen and mouse click doesn't response.
Any ideas?
XGrabKeyboard() (if successful - be sure to check the return value), redirects all key events to your client.
So if your "..." inside the while(true) does not properly handle those key events, or does not ever ungrab (XUngrabKeyboard) or release sync events (XAllowEvents, only applies to GrabModeSync), then the keyboard would appear to lock up.
The boolean parameter is owner_events which indicates whether to report key events always to the window provided to XGrabKeyboard, or report them to the window they normally would have gone to without the grab. Typically you want False (report to the grab window).
For typical uses of XGrabKeyboard (I don't know your use-case) the parameters you would want are:
grab window = some window in your app that relates to the reason for the grab
owner_events=False to send all events to that window
pointer_mode=Async to not screw with the pointer
keyboard_mode=Async to just redirect all key events and avoid need for AllowEvents
time=the timestamp from the event triggering the grab, ideally, or one generated by changing a property and grabbing the timestamp off the PropertyNotify
But, it depends. To give any definitive answer you'd probably need to post a compilable program, I think the bug is likely in the "..." part of your code. Try narrowing your app down to a single-file test case that can be run by others perhaps. Or explain more why you are grabbing and what you're trying to accomplish in the big picture.
I cant help with the XGrabKeyboard function - I havent used it before and dont know how it works - but I can suggest another way of getting the keyboard events.
When creating my window using XCreateWindow, the last argument is a XSetWindowAttributes object. This object has a member event_mask, which you can use to choose which events your window will receive.
I set mine like this:
XSetWindowAttributes setWindAttrs
setWindAttrs.event_mask = ExposureMask
| KeyPressMask
| KeyReleaseMask
| ButtonPressMask
| ButtonReleaseMask;
That will mean you receive events for keyboard key presses and mouse button clicks if you pass this object to XCreateWindow on window creation.
Also another note you can use XPending(pDisplay) to check if there are still events waiting to be handled - so it could replace true in your while(true) line.
Edit: Also your freezing issue could be that you dont return false anywhere in your while loop? It may be stuck in an infinite loop, unless you just removed that bit for the post. Try replacing true with xpending as I suggested above and it may fix the issue, or just returning false after handling the event, but this would only handle one event per frame rather than handling all the currently pending events like XPending would do, and I assume that is what you want to do.

MFC dialog frozen

I need help how to unfreeze my dialog box. I'm using MFC and I have an infinite loop I want to execute when a button is pressed. However, the dialog box freezes when the infinite loop starts. Now I looked at this thread where someone was having a similar problem.
Unfortunately I tried multithreading but I found out that It can't work for me because I'm using an api that uses OLE automation and I'm getting an unhandled memory exception. I think this is because program uses the serial port and i read somewhere you can only use the handle to the serial port in one thread.
My program is simply to see if someone has dialed in to my modem and wait for them to send me a file, then hangup. Here is my loop.
while(1)
{
//get rid of input buffer
ts->_this->m_pHAScript->haReleaseRemoteInput();
ts-> _this->textBox->SetWindowTextA("thread Commence");
//wait for connected
if(success = ts->_this->m_pHAScript->haWaitForString("CONNECT",timeout))
{
//getFile
if(success = ts->_this->m_pHAScript->haWaitForXfer(5000))
{
//hangup
ts->_this->haTypeText("+++ath\r");
}
}
}
Is there a way to unfreeze the dialog box?
Add this code inside while loop:
MSG msg;
while(PeekMessage(&msg, GetSafeHwnd(), 0, 0, PM_REMOVE))
{
DispatchMessage(&msg);
}
The GUI in Windows relies on a message loop - somewhere in your code, either explicitly or hidden in a framework, there's a loop that checks for a message in a queue and processes it. If anything blocks the code from returning to that loop, the GUI gets frozen.
There are a few ways around this. One was given by David Brabant, essentially duplicating the loop. Another is to start a new "worker" thread that runs the blocking operation independently. If your message loop has a function that it calls when it is idle, i.e. no more messages are in the queue, you can do some processing there; that's not possible in your example however.

Zing Chart Memory Leak, causing browser to crash

We are currently rendering 50-100 canvas on browser window. Browsers both IE and chrome crashes.
On further investigation, looks like memory is creeping up steadily. Causing browser to crash.
We are building a solution to print charts To achieve this,
We are displaying all the charts in a simple page (iframe) charts are not visible to user
Using chart id to getting image data.
Since charts are not visible we can ‘destroy’ or remove them from memory once they are rendered.
But ‘destroy’ does not reduce charts memory footprint
Tried setting object to null. this did not work either
Attached snippet for your reference,
var runner = 0
zingchart.complete = function (dataObj) {
for (i = 0; i < ZingChartCollection.length; i++) {
if (dataObj["id"] == ZingChartCollection[i].ChartId) {
var data = zingchart.exec(dataObj["id"], "getimagedata", '{"filetype": "png"}');
zingchart.exec(dataObj["id"], 'destroy');
zingchart.exec();
if (runner < 200) {
document.getElementById("displayCount").value = runner;
render();
}
else {
//zingchart = null;
}
runner++;
}
}
}
Any suggestions would be great.
Here's a note regarding the issue from the ZinChart dev team:
The issue here is that the render() -> complete event -> image generation -> destroy() is a closed loop.
The way the ZingChart lib works, in order to fire the complete as soon as possible, the code was binding the context menu events AFTER the complete was fired.
So, since destroy was being called immediately, the context menu events were left out in the open, and with 50-100 charts it starts to add, leading to memory leaks.
This will be changed & fixed in the next versions in order to fire the complete event after the context menu setup, however, with the current setup, there are two options:
use mode:static on render() since the idea is to get the static image out of the chart. This skips event binding so memory leak will no longer be an issue.
Also, since less canvas objects will be used, this will dramatically decrease the memory needed per chart.
if you need the complete functionality of the charts (although not needed in this particular case), call the destroy() in a delayed function via setTimeout. This will allow
for the context menu events to be set, so destroy() will also unbind them.

Resources