In my app I have three internet operations that run at once. They don't depend on each other so I run each of them in a background thread. They each need to be complete though before my app can move on to the completion handler.
The method that starts each of the three receives as a parameter, block code that functions as a completion handler. This method also has a local variable called internetOperationsRemaining that I set equal to 3 before I start each of the three internet operations.
When each of the internet operations is complete I decrement internetOperationsRemaining on the main thread. This results in internetOperationsRemaining == 0 when they are all complete.
To listen for this condition I run a tight loop on another background thread that simply loops on itself waiting for internetOperationsRemaining to equal 0. Once that happens I call the completion handler that was passed in as a parameter as previously described.
//Spawn a background thread and loop in it until
//allInternetOperationComplete == true.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while(internetOperationsRemaining > 0)
{
//Just spins in here on a background thread waiting
//on the internet to finish.
}
//Now that internetOperationsRemaining == 0, kill the NSURL session
//and call the completion handler on the main thread.
dispatch_async(dispatch_get_main_queue(), ^{
[session finishTasksAndInvalidate];
completionHandler();
});
});
The strange behavior that I am seeing is that the app runs perfectly if I have debug set in the scheme, and it doesn't if I have release selected. It simply never breaks out of the while loop.
If I insert some trivial code in the while loop to slow things down just a little it works fine in both debug and release.
while(internetOperationsRemaining > 0)
{
//Just spins in here on a background thread waiting
//on the internet to finish.
int i=0;
++i;
}
I am at a loss to explain this behavior. The tight loop is on a background thread so the app remains responsive to user input as would be expected. I realize that the release scheme introduces optimizations, but I am surprised it actually changed the apps behavior.
Without running code to check, I would think that what is going on is some sort of compiler optimisation which only occurs in Release code.
I think the real problem though is more about design. Using counters and having a thread spinning is not great. I would suggest looking into using NSOperations. You can setup hierarchies of operations so that your completion operation is dependant on the other three. Go read up on using operations, concurrent queues and dependencies and you will get the idea.
Related
When responding to an event in a textbox using C++/winrt I need to use ScrollViewer.ChangeView(). Trouble is, nothing happens when the call executes and I expect that is because at that moment the code is in the wrong thread; I have read this is the cause for lack of visible results from ChangeView(). It appears that the proper course is to use CoreDispatcher.RunAsync to update the scroller on the UI thread. The example code for this is provided only in C# and managed C++, however, and it is a tricky matter to figure out how this would look in normal C++. At any rate, I am not getting it. Does anyone have an example of the proper way to call a method on the UI thread in C++/winrt? Thanks.
[UPDATE:] I have found another method that seems to work, which I will show here, though I am still interested in an answer to the above. The other method is to create an IAsyncOperation that boils down to this:
IAsyncOperation<bool> ScrollIt(h,v, zoom){
co_await m_scroll_viewer.ChangeView(h,v,zoom);
}
The documentation entry Concurrency and asynchronous operations with C++/WinRT: Programming with thread affinity in mind explains, how to control, which thread runs certain code. This is particularly helpful in context of asynchronous functions.
C++/WinRT provides helpers winrt::resume_background() and winrt::resume_foreground(). co_await-ing either one switches to the respective thread (either a background thread, or the thread associated with the dispatcher of a control).
The following code illustrates the usage:
IAsyncOperation<bool> ScrollIt(h, v, zoom){
co_await winrt::resume_background();
// Do compute-bound work here.
// Switch to the foreground thread associated with m_scroll_viewer.
co_await winrt::resume_foreground(m_scroll_viewer.Dispatcher());
// Execute GUI-related code
m_scroll_viewer.ChangeView(h, v, zoom);
// Optionally switch back to a background thread.
// Return an appropriate value.
co_return {};
}
I wrote this little program which is supposed to print the current frontmost application twice, with a 3-second break in between.
void printFrontmostApp() {
NSRunningApplication *frontmostApplication = [NSWorkspace sharedWorkspace].frontmostApplication;
NSLog(#"%#",frontmostApplication);
}
int main(int argc, const char * argv[]) {
#autoreleasepool {
printFrontmostApp();
sleep(3);
printFrontmostApp();
}
return 0;
}
When I ran this program, I realised that frontmostApplication is not refreshed when it is called the second time. I found the solution here. But I still have two questions:
1) I want to know why the frontmostApplication is not updated.
2) How do I force it to refresh every time I call it? I don't want to receive a notification every time the frontmost application deactivates, because it is a little inefficient for my purposes.
Edit:
Just to be crystal clear, let's suppose the time now is 10:00:00. I call printFrontmostApp, and it prints "Xcode" to the console, because Xcode is the current frontmost app. Then the program sleeps for 3 seconds. At 10:00:01, I opened another app, say TextEdit. At 10:00:03, my program calls printFrontmostApp for the second time. I expect it to print "TextEdit", which is the current frontmost application. But it prints "Xcode" instead. I can't understand this behaviour.
Can someone please explain what happens at 10:00:03? The function seems to "remember" the value of frontmostApplication at 10:00:00 and retains it when it is called the second time. I thought that any memory will be released once it goes out of scope, so why is this happening?
And how do I get my program to get the frontmost app at 10:00:03? I can get the frontmost app at 10:00:00, I should be able to do the same 3 seconds later right?
The documentation for -[NSWorkspace runningApplications] — not the method you're using, but related — says:
Similar to the NSRunningApplication class’s properties, this property will only change when the main run loop is run in a common mode. Instead of polling, use key-value observing to be notified of changes to this array property.
From the NSRunningApplication documentation:
Properties that vary over time are inherently race-prone. For example, a hidden app may unhide itself at any time. To ameliorate this, properties persist until the next turn of the main run loop in a common mode. For example, if you repeatedly poll an unhidden app for its hidden property without allowing the run loop to run, it will continue to return NO, even if the app hides, until the next turn of the run loop.
It's a near certainty that the same principle applies to -frontmostApplication even though the documentation doesn't say so explicitly. You will never get different results by polling without allowing the run loop to run.
For 1) the answer is the same described in the question you have linked: You have to observe this notification, that tells you when a new application was activated:
NSWorkspaceDidActivateApplicationNotification
About 2) You have different observers for activation and deactivation like:
NSWorkspaceDidDeactivateApplicationNotification
So your are not going to observe notifications that you are not registered, please take a look at NSWorkspace Notifications for a comprehensive list.
Otherwise, please define your question about refreshing/polling (that I think it's not a good idea anyways).
There are method in NSRunLoop and CFRunLoop, To run to particular time
CFRunLoopInMode and NSRunLoop - runUntillDateT
These methods specify a time to run until.
But, I wanted process all the messages in the runLoop and exit if it is done and idle.
Because some of the runLoop sources can have indefinite time to process. So, I cannot mention the time.
You can use CFRunLoopRunInMode to run the event loop for one pass, and it tells you whether it handled any sources. So you can try something like this:
while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, 1) == kCFRunLoopRunHandledSource) {
// nothing
}
Another approach you could try is to create a CFRunLoopObserver with an activities argument of kCFRunLoopBeforeWaiting. This observer will be called just before the run loop goes to sleep waiting for a source or timer to fire. In the observer's callout, you can simply call CFRunLoopStop(CFRunLoopGetCurrent()).
My WinForm apps needs to execute complex query with significant execution time, I have no influence (about 10mins)
When query is executing user sees 'application not responding' in task manager, which is really confusing to user, also not very professional...
I believe that query shall be executed in different thread or so. Have tried some approaches but have difficulties to make it really working (execute query, force main application wait result, return back to main app, possibility to cancel execution etc)
I wonder if you have own / good working solution for that. Code samples would be also very welcome :)
Also I believe there might exist some ready to use utilities / frameworks allowing simple execution of that.
The simplest approach here would be to do that work from a BackgroundWorker. MSDN has examples for this. This then executes on a worker thread, with events for completion/error/etc. It can also support cancel, but your operation needs to be coded to be interruptable.
Another approach is the Task API in 4.0; but if you use this you'll need to get back to the UI thread (afterwards) yourself. With BackgroundWorker this is automatic (the events are raised on the UI thread).
If ExecuteQuery if the method you want to execute, you can do:
void SomeMethod() {
var thread = new Thread(ExecuteQuery);
thread.Start();
}
void ExecuteQuery() {
//Build your query here and execute it.
}
If ExecuteQuery receives some parameters, like:
void ExecuteQuery(string query) {
//...
}
You can do:
var threadStarter = () => { ExecuteQuery("SELECT * FROM [Table]"); };
var thread = new Thread(ThreadStarter);
thread.Start();
If you want to stop the execution of the background thread, avoid calling thread.Abort() method. That will kill the thread, and you do not want this, because some incosistency could appear in your database.
Instead, you can have a bool variable visible from ExecuteQuery and from outside you can set it to True when you want to stop it. Then all you have to do is check in some parts of the code inside ExecuteQuery if that variable is still True. Otherwise, do some rollback to maintain the database stable.
Be sure you set that bool variable volatile
Edit:
If you want the UI to wait from the background thread, I usually do:
Start the background thread
Start some progress bar in the UI
Disable some controls (like buttons, etc) to avoid the user to click them while the background thread is working (eg: If you're executing the thread when a user clicks a button, then you should disable that button, otherwise multiple queries will be ocurring at the same time).
After finished the thread, you can stop progress bar and enable controls again.
How to know when the thread finished? You can use Events for that. Just create an event and fire it when it finishes, and do whatever you want inside the event handler...
Be sure you're accessing correctly to UI controls from the background thread, otherwise it will give you an error.
If you are new to threads and task is simple (as it seems), you should try to use standard background worker component.
Hi I would like to pause the execution of a function in an cocoa project. I dont want to use sleep() because the function needs to resume after user interaction. I also want to avoid doing this with multiple calls to sleep.
Thanks for your responses. Ok I started the code while waiting for some answers. I then realized that sleep or pause would not be usefull to me because it freeses my whole program. I think I might have to do some threading. Here is the situation:
I have a program that uses coreplot. I also use it to debug and develop algorithms so I do lots of plots while the data is being processed (ie in the midfle of the code but I need the flexibility to put it anywhaere so I cant separate my function). I was able to do this with NSRunAlertPanel but having a message box like that doesnt make it very presentable and I cant do much with the main window while an alert is open.
I hope I am not too confusing with my explanation but if I am ill try to one line it here:
I would like to interact with my cocoa interface while one of my functions is stopped in the middle of what it is doing.
Its sounds to me like you're looking for -NSRunLoop runUntilDate:
Apple's Docs: runUntilDate
This code will cause the execution within your method to pause but still let other events like timers and user input occur:
while ( functionShouldPause )
{
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
}
Switching functionShouldPause back to false will allow the rest of the method to execute.
It seems more like you are interested in reacting to user events rather than "pausing" the function. You would probably want to put the code that you want to execute into another function that is called as a result of the user's actions.
In C you can use the pause() function in <unistd.h>. This causes the calling program to suspend until it receives a signal, at which point the pause call will return and your program will continue (or call a signal handler; depending on what signal was received).
So it sounds like you want to break the function into two parts; the bit that happens before the sleep and the bit that happens afterward. Before going to sleep, register for a notification that calls the "after" code, and can be triggered by the UI (by an IBAction connected to whatever UI element). Now instead of calling sleep(), run the run loop for the period you want to go to sleep for, then after that has returned post the "after" notification. In the "after" code, remove the object as an observer for that notification. Now, whichever happens first - the time runs out or the user interrupts you - you get to run the "after" code.
Isn't there a clock or timer function? When your button is pressed start running a loop like timeTillAction = 10 and do a loop of timeTillAction = timeTillAction - 1 until it reaches 0 then run whatever code after the 10 seconds.
Sorry if this isn't well explained.