There are lots of QA's and articles online explaining how to work with runspaces and shared objects' data in PowerShell using synchronization, locking, etc. But I couldn't find anything about executing method of PSObject, passed by [reference] from the main thread to another runspace. When called from within the runspace, I found that the method of the passed object executes on the main thread.
Is there a way to make the method run in the runspace, other than rewriting it as a separate function and adding that function to the runspace via [powershell]::Create().AddScript()?
Related
My main question is does 1 RunSpace represent 1 thread.
I read this post:
Process vs Instance vs Runspace in PowerShell
And originally I understood it as:
You have a currently running powershell process.
A runspace object is created within powershell's process address space.
It sets up and manages it's own thread within the main process.
You would create an object that represent the script you want to run in that thread with [powershell]::create()
Then pass it to the runspace to be executed within the thread it manages.
However after looking at the PSThreadOptions
https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.psthreadoptions?view=pscore-6.2.0
I'm a little confused - if (as I originally thought) 1 runspace = 1 thread why does it have an option to create a new thread for each invocation (I'm asuming they mean for each time you call .invoke() on an already created object and not just if you reinstanciate it) and also in what instance might someone use the current thread?
Any clarification on how these options work any corrections you can offer to my current understanding of things would be very much appreciated
Many Thanks
Nick
I'm using performBlock on my NSManagedObjectContexts so that my changes happen on the right queue for the given context. My question is - if I'm making a lot of changes and calling methods from within performBlock - is there an easy way to ensure that I use objects from the proper context.
Example:
I have an activeAccount iVar ( created on the Main Queue ) that is a NSMangedObject for the current account in the application. I have some instance methods that use the activeAccount object to perform certain tasks - getting data, setting data. So my question is if I am doing something on a background NSManagedObjectContext and I call one of these shared methods - is there a pattern I can use so that in these methods I know to either use the current activeAccount iVar or get a new one. Also, if I needed to do something that requires a NSManagedObjectContext - how do I know which one to get/use.
One method I have for knowing which NSManagedObjectContext to use is I have a method that checks if it is running on the current thread - it then knows to return the main thread's context or the background thread's context. Also, if I'm on the background thread, am I allowed to read the Object ID of the activeAccount that lives on the main thread so that I can get a copy of it on the background thread? Thanks in advance.
Brian,
Thread confinement can be a tricky proposition to maintain. The key thing you need to maintain is using objects in their proper MOC. As every managed object maintains a link to both its host MOC and its object ID, this is really easy to ensure. For example:
NSManagedObjectContext *newMOC = NSManagedObjectContext.new;
newMOC.persistentStoreCoordinator = oldActiveAccount.managedObjectContext.persistentStoreCoordinator;
ActiveAccount *newActiveAccount = [newMOC objectWithID: oldActiveAccount.objectID];
Now every instance you access from newActiveAccount is created in the newMOC and is, hence, thread confined to that MOC. objectIDs are persistent. The -persistentStoreCoordinator is rarely, if ever, changed on the mainMOC. Hence, the above code is properly confined. There are issues with the above technique if the source MOC is transient. Hence, I cannot guarantee the above code works with respect to two background MOCs.
Andrew
I have to ask first, why are you having so many contexts in use at the same time?
I use one for background operations and one for main thread. If I need to create another one for discardable changes, I'll just create it and pass it on, so now my self.managedObjectContext points to the draft context. I will never let my managed objects to live in a scope where they could access a multitude of contexts.
It is not entirely clear if you are writing for iOS or OSX, but with iOS for example:
If I need to push a new view controller into navigation stack I will initialize my destination view controller's managedObjectContext ivar as well as any NSManagedObject subclass instances. Since in -prepareForSegue: I know whether I'll create a draft context or just pass on my current one, I also know whether I need to initialize those managed object instances by referencing them by their IDs from newly created context or I can just pass them on.
Now inside my view controller I can take it for granted that my managed objects are always tied to the self.managedObjectContext.
I've using the QT API in C++, but I imagine answers can come effectively from people without any prior experience with QT.
QT has a function in its XML-handling class, called setContent(), which is specified as non-reentrant. When called, setContent() reads an XML file into memory, and returns it as a data structure.
As I understand it, a non-reentrant function is one that is not safe to call simultaneously from multiple threads even if the function is called to operate on different files/objects.
So based on this, my understanding is that I would not be able to have more than one thread that opens XML files using this function unless somehow both of these threads are protected against accessing the setContent() function at the same time.
Is this correct? If so, seems like a really poor way to write an API as this doesn't seem like a function at all that intuitively would raise multi-threading problems. In addition, no mutex is provided at all by the API.
So in order to use this function in my multi-threaded program, where more than one thread will be opening different XML files, what's the best way to handle access to the setContent() function? Should I create an extern mutex in a header file on its own that is included by every file that will access XML?
Looks like it's all about static QDomImplementation::InvalidDataPolicy invalidDataPolicy. It's the only static data that QDom*** classes use.
setContent and a bunch of global functions use its value when parsing, and if another thread changes it in the middle, obviously something may happen.
I suppose if your program never calls setInvalidDataPolicy(), you're safe to parse XML from different threads.
So based on this, my understanding is that I would not be able to have
more than one thread that opens XML files using this function unless
somehow both of these threads are protected against accessing the
setContent() function at the same time.
I think you're correct.
So in order to use this function in my multi-threaded program, where
more than one thread will be opening different XML files, what's the
best way to handle access to the setContent() function? Should I
create an extern mutex in a header file on its own that is included by
every file that will access XML?
Again, I tend to agree with you regarding the mutex. (By the way, Qt provides the QMutex) But I'm not sure what you mean by an extern mutex in a header file, so I'll just make sure to instantiate exactly one mutex, and dispatch a pointer to this mutex to all the threads that require it.
This seems to be an easy task, I just don't know which way to start using OmniThreadLibrary:
I create a Task that does some processing in the background. The results are stored in fields of the task class and are continuously filled with new values.
Now the main thread wants to read these fields and display their values from time to time.
Therefore it needs to access these fields and make sure that they are not written to at these moments (Synchronize).
How can this be done with OmniThreadLibrary?
There's no direct support for owner/thread data sharing in the OTL, because all my multithreaded experience tells me that this is always a bad thing to do. (Agree, sometimes it is the only solution but still it's a bad thing.)
You should go with the second mghie's suggestion - create an (optionally interface-based) object and pass this object (or its interface) to the thread. Something like this:
sharedData := TSharedData.Create;
task := CreateTask(worker).SetParameter('shared', sharedData).Run;
worker:
sharedData := Task.Param['shared'].AsObject as TSharedData;
Another way to solve the problem would be to send a 'please send update' message to the task whenever the user presses the UpdateNow button. That task would then respond with an object containing current state. However, if the task performs a lengthy uninterruptable calculation this solution is not really appropriate and the shared state approach works better.
Check out the OTL test 23, which implements a background file search. The SetParameter() method is used to set the search properties, the Comm channel is used to transfer results back to the main thread. The communication is already thread-safe, you need not implement any further synchronization.
Edit:
If you don't want a push but a pull model then you can of course use standard synchronization tools: an object that has a critical section which is used in all accessors to protect data from concurrent access. This object could be the task object itself, or any third object that is created by the GUI thread and passed to the task by (again) calling SetParameter(). If you don't use an object but an interface pointer you will get more safety, as the order of destruction is no longer important, the object holding the data will only be destroyed once the last reference to the interface it implements is reset.
It seems that all Guice's out-of-the-box Scope implementations are inherently Thread-based (or ignore Threads entirely):
Scopes.SINGLETON and Scopes.NO_SCOPE ignore Threads and are the edge cases: global scope and no scope.
ServletScopes.REQUEST and ServletScopes.SESSION ultimately depend on retrieving scoped objects from a ThreadLocal<Context>. The retrieved Context holds a reference to the HttpServletRequest that holds a reference to the scoped objects stored as named attributes (where name is derived from com.google.inject.Key).
Class SimpleScope from the custom scope Guice wiki also provides a per-Thread implementation using a ThreadLocal<Map<Key<?>, Object>> member variable.
With that preamble, my question is this: how does one go about creating a non-Thread-based Scope? It seems that something that I can use to look up a Map<Key<?>, Object> is missing, as the only things passed in to Scope.scope() are a Key<T> and a Provider<T>.
Thanks in advance for your time.
It's a bit unclear what you want - you don't want scopes that are based on threads, and you don't want scopes that ignore threads.
But yes, scopes are intended to manage the lifecycle of an object and say when an instance should be reused. So really you're asking "what are the other possibilities for re-using an instance beyond 'always use the same instance', 'never use the same instance', and 'use an instance depending on the execution environment of the current thread'?"
Here's what comes to mind:
Use the same instance for a fixed amount of time. The example here would be of a configuration file that's reloaded and reparsed every ten minutes.
Perform some network call to query whether a given object should be re-used (maybe it's a fast call to determine whether we need to reconstruct the object, but the call for reconstructing the object is slow)
Re-use the same object until some outside call comes in telling us to reload
Re-use the same object per thread, but not with a scope that's explicitly entered and left like the servlet scopes. (So one instance per thread)
A "this thread and child threads" scope that is based on an InheritableThreadLocal, not a plain ThreadLocal.
Related to that, a Scope and a threadpool-based ExecutorService that work togehter so that instances are shared between a thread and jobs it submits for background execution.
Pull instances out of a pool; this is tricky, since we'd need a good way to return objects to the pool when finished. (Maybe you could combine this idea with something like the request scope, so that objects can be returned to the pool when the request ends)
A scope that composes two or more other scopes, so for example we could get a configuration object that is re-read every 10 minutes except that the same instance is used through the lifetime of a given request.