I’m trying to wrap my head around threading and how it affects The Composable Architecture.
I know that Store is not threadsafe and that interactions with it, such as sending an action from an effect, must be done on the main thread.
My question is why? In what scenario could sending an action on a background thread cause problems?
Further, for effects, why couldn’t the architecture call .recieve(on:) internally as opposed to me having to do it on the outside? Does this indicate that there are scenarios where background threads are acceptable?
Related
The other day, in a code review, I saw some questions about the safety of setting a property from a worker thread. A coworker made the comment, "This property is bound to the UI, and data binding is thread-safe."
I've been using XF for a while, but always assumed this wasn't true: that if I wanted to update ViewModel properties bound to the UI I'd have to make those changes on the UI thread. I just spent a few minutes poking around the documentation, and I don't see an obvious answer other than that directly manipulating BindableProperties has thread affinity. It also matters to me if that's a blocking UI thread execution or not.
I could make a project to test it out myself, but these kind of issues always seem to be intermittent so I'd like to know I'm just missing the right documentation.
(It's relevant to investigating a crash we're seeing that happen within mainly Xamarin call stacks. We raise an event from a worker thread, a VM handles that event and updates some properties. If that's being scheduled for the UI thread, there could be some interleaving issues we didn't prepare for and I'm that much closer to addressing the crash. If it's not being scheduled for the UI thread... I'm surprised it's worked this long.)
I've been using XF for a while, but always assumed this wasn't true: that if I wanted to update ViewModel properties bound to the UI I'd have to make those changes on the UI thread.
You're right. 100% right. You can use Device.InvokeOnMainThread() for this.
To be complete, there is one case where it doesn't matter: PropertyChanged
https://github.com/xamarin/Xamarin.Forms/blob/b645064/Xamarin.Forms.Core/BindingExpression.cs#L542
In that case, the Binding is applied on the main (UI) thread.
Assumptions
We interact with the UI exclusively via binding. So only setters and getters are playing.
Getters
The code referred to in github by #Stephane, only means, that your bound getter(s) will be called in the UI thread. No more no less.
Btw, I would not rely on the source code (I mean: implementation), instead the specification what matters. Implementation can change anytime, and if the specification does not requires this, then unit tests will not check this, so there will be a big surprise...
Setters
However it is still not clear, if can you call your setter(s) in a background thread. Regardless the answer is yes or no, it implies further tasks to solve.
a) If you can call setters in any thread: This means, that your viewmodel internal data is exposed to race conditions, because will be called from the UI thread, and you will access them in a background thread. Conclusion: You must guard the data with the usual concurrency patterns, or use thread safe classes, plus: your getter and setter must be atomic.
b) If it turns out you can not call setters in any thread: Then you must use Device.InvokeOnMainThread(). But this is only the half of the story. In methods of your background thread, you are modifying say a List instance. This will be accessed in the UI thread by the getter, and you are modifying it in a background thread concurrently when you say populate it. Theoretically it is possible the user interacts with the UI during the population period, what let the binding evaluated, getter is called.
Conclusions:
If there are multiple threads accessing to the very same data, you must always lock you data.
Regardless what the current source code implies the safest way to marshall the getter and setter to the UI thread. This will not cause significant overhead: If the executions is already in the UI thread, marshall will do nothing.
Note: Even you marshall both you getters and setter to the UI thread, you will access the data in background threads so guard against race conditions or using thread safe classes are essential.
In Obj-C, what does it mean in simple terms;
"CoreData is not thread safe"
OR in general what is "not thread safe" ?
#d11wtq's answer is correct only when writing your own code or designing your own APIs.
It is entirely incorrect when working with a set of APIs and quite specifically wrong when working with Core Data.
In the context of working with Mac OS X and iOS, thread safety must always be considered in the context of working with the system APIs. Even using, say, an NSArray means that you are working with the system APIs.
OR in general what is "not thread
safe" ?
A non-thread safe API is an API where you cannot interact with the API from multiple threads simultaneously. There may also be additional restrictions that most often involve the main thread. For example, almost all drawing operations must occur on the main thread on both Mac OS X and iOS.
The Apple documentation assumes thread safety is the exceptional case. That is, an API is only thread safe if the documentation explicitly claims thread safety. If there is no mention of thread safety, you must assume that the API is not thread safe.
In Obj-C, what does it mean in simple
terms; "CoreData is not thread safe"
That statement is not quite correct, but it is a safe assumption.
In Core Data's case, the thread interaction behavior is extremely well documented.
In short, parts of the API are thread safe (the store coordinator, for example) and parts are quite explicitly not thread safe. While the MOC provides lock and unlock methods, you can also use external locking. But don't. It will be less efficient and more fragile; significantly so. In general, don't use the internal locking either. CoreData is optimized around having a context per thread/queue.
(Answer fixed based on TC's feedback. Thanks.)
UPDATE | Please see #bbum's answer. I accept that my answer is flawed and #bbum is correct.
If something is described as "not thread safe", it means that no special precautions have been taken to ensure it won't crash should two separate threads try to use it simultaneously. In general, code that is to be used by more than one thread requires explicit locks (or #synchronize blocks) wrapping around aspects of the code. In particular, any object/variable that will be modified would almost certainly cause a crash if two threads happened to write to it at the same time (since they'd be writing to the same memory address). Similarly, if one thread was reading a variable while another was writing to it, garbage would be returned and the program would likely crash.
Using #synchronized, or NSLock or a POSIX mutex etc, ensures that only one thread can execute a particular block of code at any given time. The other threads get blocked and have to wait until the lock is released. There is a slight performance hit with using locks (and of course some development overhead having to think about them), so often code expressly declares that it is not thread safe, leaving you, the adopter of the code, to place locks as needed yourself (or limit execution of the non thread-safe to a single thread).
See the Apple documentation for more information about threading and thread safety:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocThreading.html#//apple_ref/doc/uid/TP30001163-CH19-BCIIGGHG
I tried it, but I think this notification isn't coming. Is that the normal case?
No, this notification is sent by NSThread. If you're using ordinary pthreads, it won't be sent.
From the docs:
Protecting the Cocoa Frameworks For
multithreaded applications, Cocoa
frameworks use locks and other forms
of internal synchronization to ensure
they behave correctly. To prevent
these locks from degrading performance
in the single-threaded case, however,
Cocoa does not create them until the
application spawns its first new
thread using the NSThread class. If
you spawn threads using only POSIX
thread routines, Cocoa does not
receive the notifications it needs to
know that your application is now
multithreaded. When that happens,
operations involving the Cocoa
frameworks may destabilize or crash
your application.
To let Cocoa know that you intend to
use multiple threads, all you have to
do is spawn a single thread using the
NSThread class and let that thread
immediately exit. Your thread entry
point need not do anything. Just the
act of spawning a thread using
NSThread is enough to ensure that the
locks needed by the Cocoa frameworks
are put in place.
If you are not sure if Cocoa thinks
your application is multithreaded or
not, you can use the isMultiThreaded
method of NSThread to check.
It should also be noted that 'times have changed' since NSWillBecomeMultiThreadedNotification was added to Foundation. Multi-threaded programming is now much, much more common. It's now entirely within the realm of possibility, even likely, that you'll never see this notification posted in an app. Modern apps become multi-threaded very early in their life, possibly before any part of your code is ever executed. Also from the documentation:
If you are developing a Cocoa library,
you can register as an observer for
the
NSWillBecomeMultiThreadedNotification
if you want to be notified when the
application becomes multithreaded. You
should not rely on receiving this
notification, though, as it might be
dispatched before your library code is
ever called.
I'd use [NSThread isMultiThreaded] instead of relying on NSWillBecomeMultiThreadedNotification.
I am sold on KVO but if used in the obvious way it is synchronous. I would like to use it in a situation where I am firing off many KVO messages in rapid succession and it is causing my app to grind to a halt as the KVO messages are handled. Can someone suggest an approach - perhaps using NSOperation or NSThread - that will work here?
My goal is to retain the decoupled, flexibility of KVO if possible.
KVO is inherently single threaded in that the KVO notifications will be delivered on the same thread as the change.
Of course, UIKit and Cocoa both really only want you to be diddling UI elements on the main thread.
Thus, if you are doing asynchronous operations, you are most likely using threads and, if so, already have a synchronization issue in that you need to get the notifs from some thread to the main thread.
And therein lies the key. Instead of blindly forwarding each change notification as it comes in, you can coalesce the change notifications before passing them on to the main thread.
There are a variety of means via which you can do this. The specific solution is going to be quite unique to your application, most likely.
Personally, I try to avoid coalesce-and-forward of fine grained operations. I find it far simpler to tell the main thread that a particular sub-graph of objects have changed. More likely than not, the drawing code that will then make the changes visible to the user is going to need to redraw related state and, thus, related changes will be automatically reflected.
The key, as you have surmised, is to throttle the notifications so you don't bog down app responsiveness (or destroy the devices battery life).
Use the Receptionist Pattern as recommended by Apple https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/ReceptionistPattern/ReceptionistPattern.html
Check out NSNotification. It's not quite the same thing, but you can fire off notifications on background threads (with a little bit of research and work). You can maintain the nice decoupling and fire-and-forget behavior.
I have an application that opens a connection with 2 sockets (in and out) and I want to have them working in a thread.
The reason that I want them to be in a separate thread is that I don't want my application to freeze when I receive data, and this can happen anytime as long as the application is running.
Currently I have a class that handle also network communication and I run this class in an NSOperation, I'm not sure if it's the best solution.
I'm not very familiar with threading so guys if you could give me some help I would be very grateful.
Thanks
First, you should know that you can use the same socket to send and receive data — they're generally bi-directional. You should be able to share a reference to the same socket among multiple threads of execution.
Second, unless you'll be receiving large amounts of data and have experienced performance issues with your UI, I would delay optimizing for it. (Don't get me wrong, this is a good consideration, but premature optimization is the root of all evil, and simpler is generally better if it performs adequately.)
Third, NSOperation objects are "single-shot", meaning that once the main method completes, the operation task cannot be used again. This may or may not be conducive to your networking model. You might also look at NSThread. The fact that you already have the functionality "factored out" bodes well for your design, whatever turns out to be best.
Lastly, threading is a complex topic, but a good place to start (especially for Objective-C) is Apple's Threading Programming Guide.