I am using Vaadin 7.7.10 and I see many UIDetachedExceptions in the logs while using background Threads and the #Push annotation.
Please suggest how to release the resources properly in order to clean my logs.
If you do something in UI.access(..) to the UI that has been already detached, you will trigger an UIDetachedException. This is natural, if for example user has closed the browser, or there has been something in the network that has closed the connection, and thus the UI has been detached. If in your case the UIDetachedException is happening due these reasons, it is harmless. In that case, you can avoid littering your log by checking UI.isAttached() which returns false if the UI has been detached, and UI.isClosing() if the UI has already been put into the clean-up queue.
This happens because the user has closed their browser window or tab which means that the particular UI instance is no longer in use.
The best approach is usually to override the detach method in your application's UI subclass and do the cleanup there. Just remember to also call super.detach().
Another alternative is to catch the UIDetachedException that may be thrown by UI.access and do the cleanup at that point. The drawback of this approach is that you don't get the notification immediately when the UI is detached, but only when trying to do something with it.
Related
Why is it the responsibility of the programmer to call UI related methods on the main thread with:
DispatchQueue.main.async {}
Theoretically, couldn’t this be left up to the compiler or some other agent to determine?
The actual answer is developer inertia and grandfathering.
The Cocoa UI API is huge—nay, gigantic. It has also been in continuous development since the 1990's.
Back when I was a youth and there were no multi-core, 64-bit, anything, 99.999% of all applications ran on the main thread. Period. (The original Mac OS, pre-OS X, didn't even have threads.)
Later, a few specialized tasks could be run on background threads, but largely apps still ran on the main thread.
Fast forward to today where it's trivial to dispatch thousands of tasks for background execution and CPUs can run 30 or more current threads, it's easy to say "hey, why doesn't the compiler/API/OS handle this main-thread thing for me?" But what's nigh on impossible is re-engineering four decades of Cocoa code and apps to make that work.
There are—I'm going to say—hundreds of millions of lines of code that all assume UI calls are executing concurrently on the main thread. As others have pointed out, there is no cleaver switch or pre-processor that's going to undo all of those assumptions, fix all of those potential deadlocks, etc.
(Heck, if the compiler could figure this kind of stuff out we wouldn't even have to write multi-threaded code; you'd just let the compiler slice up your code so it runs concurrently.)
Finally, such a change just isn't worth the effort. I do Cocoa development full time and the number of times I have to deal with the "update control from a background thread problem" occurs, at most, once a week or so. There's no development cost-benefit analysis that's going to dedicate a million man-hours to solving a problem that already has a straight forward solution.
Now if you were developing a new, modern, UI API from scratch, you'd simply make the entire UI framework thread safe and whole question goes away. And maybe Apple has a brand new, redesigned-from-the-ground-up, UI framework in a lab somewhere that does that. But that's the only way I see something like this happening.
You would be substituting one kind of frustration for another.
Suppose that all UI-related methods that require invocation on the main thread did so by:
using DispatchQueue.main.async: You would be hiding asynchronous behaviour, with no obvious way to "follow up" on the result. Code like this would now fail:
label.text = "new value"
assert(label.text == "new value")
You would have thought that the property text just harmlessly assigned some value. In fact, it enqueued a work item to asynchronously execute on the main thread. In doing so, you've broken the expectation that your system has reached its desired state by the time you've completed that line.
using DispatchQueue.main.sync: You would be hiding a potential for deadlock. Synchronous code on the main queue can be very dangerous, because it's easy to unintentionally block (on the main thread) yourself waiting for such work, causing deadlock.
I think one way this could have been achieved is by having a hidden thread dedicated to UI. All UI-related APIs would switch to that thread to do their work. Though I don't know how expensive that would be (each switch to that thread is probably no faster than waiting on a lock), and I could imagine there's lots of "fun" ways that'll get you to write deadlocking code.
Only on rare instances would the UI call anything in the main thread, except for user login timeouts for security. Most UI related methods for any particular window are called within the thread that was started when the window was initialized.
I would rather manage my UI calls instead of the compiler because as a developer, I want control and do not want to rely on third party 'black boxes'.
check https://developer.apple.com/documentation/code_diagnostics/main_thread_checker
and UPDATE UI FROM MAIN THREAD ONLY!!!
I have couple method that depend on the network status indicator being hidden or not based on my App. I was wondering if it is possible something outside of your App control is able to turn it off or on. Any clarification will be appreciated. I downloaded an App in background and received an email in the background the indicator didn't show.
If you're referring to the networkActivityIndicatorVisible property of UIApplication, I don't believe any outside application will manipulate that property, since it is specific to the running application.
I assume you're asking because of this question, and I would recommend, like others have, not to use this to determine whether a network call has completed or not. I would put the code you want to execute at completion in a callback or delegate, depending on how the call is made. Attaching it to the networkActivityIndicatorVisible property can lead to problems if you have code in the future that shows and hides this, but you don't want this method to execute anymore.
I'm trying to make an "auto-update" process to make the user stay updated every X minutes while the app's awake. What I'm doing it's a background call every X minutes that asks the server if there are updates to make or not.
The thing is that when I make a call and the server returns YES, I've got to to update two things: my local DB and also the user interface (cause there might be changes on the interface too).
What I've got now is a thread problem. If I don't make any drawing while the app's updating I've got no issue, but when I do the app crashes.
Any ideas how could I control that threading issue?
I'm assuming you are using CoreData for your database. You need to make sure that any updates you make to the managed object context occur on the thread on which that context was created (typically the main thread).
You also need to make sure that any updates you make to the user interface also occur on the main thread.
Maybe try running the code on a background thread. one easy way to do this is preformSelectorOnBackgroundThread method...
The app I am working on fetches a bunch of different newsfeeds when it first starts up and updates any expired ones. While this is happening the interface often freezes up and you can't click anything. The actual network calls are being done on a separate thread, but the database operations are being done on the main thread. Would this cause the interface to freeze?
I have been told that I need to make it to where only two feeds to update are inserted into the network operation queue at a time so that it won't try all of them at once, but it's already set up to only do so many network calls at once. I don't understand how having less things in a queue at a time would cause it to go faster if they're just going to be put in there sequentially anyways. Please correct me if I am wrong, I'm still pretty new to this.
Any kind of help regarding what could cause the UI to freeze up during startup like this would be much appreciated!
It is always a good idea to move time consuming operation away from the main thread.
Fortunately it is pretty simple to do on iOS. If the time-consuming task is fairly simple you could consider using performSelectorInBackground
e.g:
[self performSelectorInBackground:#selector(myFunction:)
withObject:myParam];
It is however important to remberber, that you must not access the GUI from the background thread. To get objects back to the main thread use performSelectorOnMainThread
e.g:
[self performSelectorOnMainThread:#selector(myFunction:) myParamwaitUntilDone:YES];
Try applying this strategy to your database calls. Depending on your scenario you might want to wrap it up in a NSOperation or use a Thread when the cause of the freeze is found.
I have an application which needs to run several other applications in chain. I am running them via ShellExecuteEx. The order of running each of the apps is very important cause they are dependant on each other. For example:
Start(App1);
If App1.IsRunning then
Start(App2);
If App2.IsRunning then
Start(App3);
.........................
If App(N-1).IsRunning then
Start(App(N));
Everything works fine but there is a one possible problem:
ShellExecuteEx starts the application, and return almost immediately. The problem might arise when for example App1 has started properly but has not finished some internal tasks, it is not yet ready to use. But ShellExecuteEx is already starting App2 which depends on the App1, and App2 won't start properly because it needs fully initialized App1.
Please note, that I don't want to wait for App(N-1) to finish and then start AppN.
I don't know if this is possible to solve with ShellExecuteEx, I've tried to use
SEInfo.fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_NOASYNC;
but without any effect.
After starting the AppN application I have a handle to the process. If I assume that the application is initialized after its main window is created (all of Apps have a window), can I somehow put a hook on its message queue and wait until WM_CREATE appears or maybe WM_ACTIVATE? In pressence of such message my Application would know that it can move on.
It's just an idea. However, I don't know how to put such hook. So if you could help me in this or you have a better idea that would be great:)
Also, the solution must work on Windows XP and above.
Thanks for your time.
Edited
#Cosmic Prund: I don't understand why did you delete your answer? I might try your idea...
You can probably achieve what you need by calling WaitForInputIdle() on each process handle returned by ShellExecute().
Waits until the specified process has finished processing its initial input and is waiting for user input with no input pending, or until the time-out interval has elapsed.
If your application has some custom initialization logic that doesn't run in UI thread then WaitForInputIdle might not help. In that case you need a mechanism to signal the previous app that you're done initializing.
For signaling you can use named pipes, sockets, some RPC mechanism or a simple file based lock.
You can always use IPC and Interpocess Synchronization to make your application communicate with (and wait for, if needed) each other, as long as you code both applications.