Any alternative to callbacks for UI programming? - c

Let's say I have a several step process like during software installation for example.
Each step display a text box and wait for the user to click the "next" button.
The standard way to do it is to have a callback like this:
process
{
Dialog1() // Will call callback2 when closed
}
callback2()
{
Dialog2() // Will call callback3 when closed
}
callbak3()
{
Dialog3() // Will call callback4 when closed
}
This technique makes the code quite unreadable when there is a lot of steps as you have to
divide you process into each successive callback function (not to mention save
context from one to another).
What would be an easier to read way to do it ? Ideally the process should read like
this:
process()
{
Dialog1()
callback1() // stop method until closed
Dialog2()
callback2() // stop method until closed
Dialog3()
callback3() // stop method until closed
}
Problem with this is that you can't stop the UI thread. Any idea or work around would be very appreciated.
PS: this as to work in C or Objective C
ANSWER
So after having discovered coroutines thanks to Martin B I've found this page: https://stackoverflow.com/posts/4746722/edit and ended up using this code:
define coRoutineBegin static int state=0; switch(state) { case 0:
define yield do { state=__LINE__; return;
case __LINE__:; } while (0);
define coRoutineEnd }
void process()
{
coRoutineBegin
Dialog1()
yield
Dialog2()
yield
Dialog3()
yield
Dialog4()
yield
coRoutineEnd
}

You're looking for coroutines, which provide exactly the concept you're looking for: Yielding control from a function without exiting it. In essence, your code would look like this:
process()
{
Dialog1()
yield
Dialog2()
yield
Dialog3()
}
Unfortunately, coroutines aren't supported natively by C or Objective C and are hard to implement generically without resorting to ugly hacks. However, you may be able to take the concept as a starting point for a special-case construct for your situation.

You could use a Mutex or similar concept where the dialog is opened and run in a different thread.
Here is a post with an example I think is valid:
Synchronization/wait design for cross-thread event signaling (Obj-C)?

I don't quite understand the problem. Why doesn't showing a modal dialog work? Modal dialogs block until they are dismissed so your logic would look like:
Dialog1()
Dialog2()
Dialog3()
Another solution is to have your dialogs or callbacks or whatever send events. You then bind to those events. Your main logic would then look like this (sorry, I don't know how to do GUI examples in C/Objective-C, so I'll use Tcl/Tk because its highly readable):
bind $rootWindow <<Step1>> showDialog1
bind $rootWindow <<Step2>> showDialog2
bind $rootWidow <<Step3>> showDialog3
# kick off the first step
event generate $rootWindow <<Step1>>
The showDialogX functions would do whatever they need to do, then generate an event saying "I'm done, ready for the next step".

Related

SetWindowPos/ShowWindow with a timeout

I'm using the SetWindowPos function for an automation task to show a window. I know that there are two ways that Windows provides to do this:
Synchronously: SetWindowPos or ShowWindow.
Asynchronously: SetWindowPos with SWP_ASYNCWINDOWPOS or ShowWindowAsync.
Now, I'd like to get the best of both worlds: I want to be able to show the window synchronously, because I'd like it to be done when the function returns. But I don't want the call to hang my process - if it takes too long, I want to be able to abort the call.
Now, while looking for an answer, the only thing I could come up with is using a separate thread and using SendMessageTimeout, but even then, if the thread hangs, there's not much I can do to end it except of TerminateProcess, which is not a clean solution.
I also have seen this answer, but as far as I understand, it has no alternative for native WinAPI.
The answer in the question you linked to simply loops until either the desired condition occurs or the timeout expires. It uses Sleep() every iteration to avoid hogging the processor. So a version for WinAPI can be written quite simply, as follows:
bool ShowWindowAndWait(HWND hWnd, DWORD dwTimeout) {
if (IsWindowVisible(hWnd)) return true;
if (!ShowWindowAsync(hWnd, SW_SHOW)) return false;
DWORD dwTick = GetTickCount();
do {
if (IsWindowVisible(hWnd)) return true;
Sleep(15);
} while (dwTimeout != 0 && GetTickCount() - dwTick < dwTimeout);
return false;
}
Unfortunately I think this is the best you're going to get. SendMessageTimeout can't actually be used for this purpose because (as far as I know anyway) there's no actual message you could send with it that would cause the target window to be shown. ShowWindowAsync and SWP_ASYNCWINDOWPOS both work by scheduling internal window events, and this API isn't publicly exposed.

Terminate activity diagram from subactivity

I´m trying to draw an UML activity diagram for a fnction that is (highly simplified) represented by the following code snippet. My intention is to have a subactivity for the lines that check the mode parameter (if-else).
ErrorType DoSomething(int mode) {
if(mode==MODE1) {
...
}
else {
return MODE_NOT_AVAILABLE;
}
SomethingElse...
return NO_ERROR;
}
You can see, the return-Statement in the else-Block leads to termination of function DoSomething. So if it´s executed, there is no way for SomethingElse... to be executed.
As I mentioned, this else-block should be in a subactivity.
How do I visualize that an action in a subactivity (return MODE_NOT_AVAILABLE) has the consequence that it´s parental activity diagram has to be in a final state?
In the following picture you can see my try to solve it. Is this a correct solution?
Since you are dealing with some kind of exception, I'd model it with an exception handler like you see here http://www.sparxsystems.com.au/images/screenshots/uml2_tutorial/ad11.GIF. Even though your concrete implementation uses if/else, that should be a way which makes it easy to understand what you want to achieve (prevent the subroutine from being executed in wrong mode).
You can see more details about the notation here: http://edn.embarcadero.com/article/30169
It depends on how much you want to dictate the actual implementation. UML itself is langage-unaware, and so are most stakeholders.

Stop a CPU-intensive operation by pressing a GTK button

I'm extending a GTK-application that does a group of operations that takes high CPU loads. I want to include the possibility to stop this operation by clicking on a button in the GUI.
The problem is that, as expected, the signal coming from the button is actually fired just after the operation is completed.
For now, the code kinda looks like this:
[...]
// code snippet to show the dialog and to enable user interactions with the buttons on the lower side of the window
while(TRUE) {
gint run = gtk_dialog_run (window_main);
if (run == GTK_RESPONSE_APPLY) {
gboolean success = start_long_operation();
}
else if (run == GTK_RESPONSE_HELP) {
open_about();
}
else if (run == GTK_RESPONSE_CANCEL) {
stop_long_operation();
}
else {
gtk_widget_destroy (window_main);
return;
}
}
I've declared a global variable busy_state that is checked by the long operation's function: if it is TRUE, simply the inner loop continues to cycle. Else, the loop exits and the function returns a result.
stop_long_operation() simply sets this global var to FALSE.
As written before, I can't press the "stop" button and "send" GTK_RESPONSE_CANCEL until the operation finishes, because it blocks the entire window.
I've tried the use of while (g_main_context_iteration(NULL, FALSE)) trick inside the stop_long_operation() function, as explained in the gtk's docs, but without results.
Do I really need to set up a multithread functionality? Can I avoid this?
Thanks for the help.
If you can break up your long operation into multiple smaller tasks you may be able to avoid using threads. The easiest way would be to just create a callback that you would pass to g_idle_add (or g_idle_add_full). Each time the callback runs it does a small amount of work, then returns TRUE. When the the task is completed, return FALSE and the callback not be run again. When you would like to interrupt the task, simply remove the callback by passing the value returned by g_idle_add to g_source_remove.
If you can't break up the operation then threads are pretty much your only choice. g_thread_new is the low-level way to do that, but it's generally easier to use a GThreadPool. A more advanced option would be to use g_simple_async_result_run_in_thread.
Here's another option if you don't want to use threads (although you should use threads and this is very insecure):
Use processes. Processes are much simpler, and can allow you some greater flexibility. Here's what you need to do:
Create another C/C++/Any language you want program that does the task
Spawn it using spawn() or popen()
(Optional) Pass arguments using the command line, or IPC
When the button is pressed, use either the kill() call on UNIX, or the Win32 kill function to kill the process. You can use SIGTERM on UNIX and register a handler so that you can have a controlled shutdown.

WPF MVVM update label text

My label text isn't updating properly in my 3.5 WPF MVVM app.
The do work part lasts long enough that you can see the waiting mouse pointer.
All I ever see is "Parsed" in the label, which is Bound to InfoText.
the Dispatcher and do work lines are in a Command's method.
Ideas?
The code
Dispatcher.Invoke((Action<string>)SetInfoText, "Start Parsing");
//do work
Dispatcher.Invoke((Action<string>)SetInfoText, "Parsed");
private void SetInfoText(string text)
{
InfoText = text;
}
private string _infoText;
public string InfoText
{
get
{
return _infoText;
}
set
{
_infoText = value;
OnPropertyChanged("InfoText");
}
}
The only thing I can think of to explain it is that you're doing the work on the UI thread. This would prevent the dispatcher from redrawing until your work is done. The work being passed in Invoke is placed in the event queue, meaning it will be performed when idle.
The proper way to fix it is to do the work on a separate thread. If you're looking for workarounds though, look here.
Reference: MSDN
EDIT:
There are lots of ways to perform the work on another thread. Read up on BackgroundWorker, ThreadPool, Task Parallell Library, Threads. :)
Here's a really simple way to do the work in a background thread:
System.Threading.ThreadPool.QueueUserWorkItem( state =>
{
Dispatcher.Invoke((Action<string>)SetInfoText, "Start Parsing");
System.Threading.Thread.Sleep(5000); // Simulate work
Dispatcher.Invoke((Action<string>)SetInfoText, "Parsed");
});
Application.Current.Dispatcher.BeginInvoke(new Action(() => this.InfoText="Start Parsing"));
this works for me.
nevertheless i would put my long running process in a backgroundworker. so ui thread will not get blocked.
edit: if you do all your work in ui thread you should look at the overload for BeginInvoke - you can pass a DispatcherPriority. may be this helps too

C: pattern for returning asynchron error from background thread?

I'm writing an open source C library. This library is quite complex, and some operations can take a long time. I therefore created a background thread which manages the long-running tasks.
My problem is that I have not yet found an elegant way to return errors from the background thread. Suppose the background thread reorganizes a file or does periodic maintenance, and it fails – what to do?
I currently see two options:
1) if the user is interested in seeing these errors, he can register a callback function.
I don't like this option – the user doesn't even know that there's a background thread, so he will most likely forget about setting the callback function. From usability point of view, this option is bad.
2) the background thread stores the error in a global variable and the next API function returns this error.
That's what I'm currently doing, but I'm also not 100% happy with it, because it means that users have to expect EVERY possible error code being returned from every API function. I.e. if the background thread sets an IO Error, and the user just wants to know the library version, he will get an IO error although the get_version() API call doesn't access the disk at all. Again, bad usability…
Any other suggestions/ideas?
Perhaps for the "long running operations" (the ones you'd like to use a thread for) give users two options:
a blocking DoAction(...) that returns status
a non-blocking DoActionAsync(..., <callback>) that gives the status to a user provided callback function
This gives the user the choice in how they want to handle the long operation (instead of you deciding for them), and it is clear how the status will be returned.
Note: I suppose that if they call DoActionAsync, and the user doesn't specify a callback (e.g. they pass null) then the call wouldn't block, but the user wouldn't have/need to handle the status.
I am interested in knowing how the completion status informed to the caller of API.
Since the background thread carries out all the execution. Either the foreground thread chooses to wait till the completion, like synchronous. Or the foreground thread can do other tasks, registering for a callback.
Now, since the first method is synchronous, like your usage of a global variable. You can use a message queue with 1 member, instead of your global variable. Now,
- Caller can either poll the message queue for the status
- Caller can block wait on the message queue for status
What I can think of,
But if I am the caller, I would like to know the progress status, if the time taken is very ... very long. So better to give some kind of percentage completion or something to enable the end user to develop much better application with progress bar and all.
You should keep a thread-safe list (or queue) of error events and warnings. The worker thread can post events to the list, then the main thread can read events from the list, one at a time, or in a batch to prevent race conditions. Ideally, the main thread should fetch a copy of the event queue and flush it so there is no change of duplicating events in the case of multiple main or worker threads. Events on the list would have a type and details.
If you're providing a library and try to hide expensive work via a thread I'd suggest to not do it that way. If something is expensive it should be visible to the caller and if it bugs him, he should take care of backgrounding/threading himself. That way he also has full control over the error.
It also takes the control over his process away from the developer who uses your library.
If you still want to use threads I'd suggest to really follow the callback-route but make it clearly visible in the API and documentation that there will be a background thread running on this task and therefore the callback is necessary.
Best way would be if you offered both ways, synchronous and asynchronous, to the users of the library so they can choose what fits best for them in their specific situation.
Thanks for all the good answers. You provided me with a lot of material to think about.
Some of you suggested callbacks. Initially, i thought a callback is a good idea. But it just moves the problem to the user. If a user gets an asynchronous error notification, how will he deal with it? he will have to interrupt and/or notify his synchronous program flow, and that's usually tricky and often breaks a design.
The solution i'm doing now: if the background thread generates an error, the next API call will return an error BACKGROUND_ERROR_PENDING. With a separate API function (get_background_error()) the user can look at this error code, if he's interested in it.
Also, i added documentation so users don't be too surprised if this error is returned.
You might take a look at java's Future API for an alternate mechanism for dealing with asynchronous calls and errors. You could easily substitute the checked exceptions with some isError() or getError() methods if you preferred.
I agree with Sean. An message queue with an event loop.
If there is an error the background thread can insert into the queue. The event loop will block until a new message becomes available.
I have used Apache Portable runtime time with great success with this design in building telecomms servers with a high transaction rate. It has never failed.
I use 1 thread to inserting into the queue, that would be your background thread. The event loop will run in another thread and block until a new message is inserted.
I would recommend APR thread pool with APR FIFO queue (which is also thread safe).
Quick design here:
void background_job()
{
/* There has been an error insert into the queue */
apr_status_t rv = 0;
rv = apr_queue_push(queue, data);
if(rv == APR_EOF) {
MODULE_LOG(APK_PRIO_WARNING, "Message queue has been terminated");
return FALSE;
}
else if(rv == APR_EINTR) {
MODULE_LOG(APK_PRIO_WARNING, "Message queue was interrupted");
return FALSE;
}
else if(rv != APR_SUCCESS) {
char err_buf[BUFFER_SIZE];
MODULE_LOG(APK_PRIO_CRITICAL, "Failed to push to queue %s", apr_strerror(rv, err_buf, BUFFER_SIZE));
return FALSE;
}
return TRUE;
}
void evt_loop()
{
while(continue_loop) {
apr_status_t rv = 0;
rv = apr_queue_pop(queue, data);
if(rv == APR_EOF) {
MODULE_LOG(APK_PRIO_WARNING, "Message queue has been terminated");
return FALSE;
}
else if(rv == APR_EINTR) {
MODULE_LOG(APK_PRIO_WARNING, "Message queue was interrupted");
return FALSE;
}
else if(rv != APR_SUCCESS) {
char err_buf[BUFFER_SIZE];
MODULE_LOG(APK_PRIO_CRITICAL, "Failed to pop from the queue %s", apr_strerror(rv, err_buf, BUFFER_SIZE));
return FALSE;
}
return TRUE;
}
}
Above is just some simple code snippets, if you want I post more complete code.
Hope that helps

Resources