Run an anonymous block on a specific background thread - objective-c

At first glance it seemed like an easy question, but I just can't figure how to run an anonymous block on a certain background thread i.e. I am looking for the blocks equivalent of -performSelector:onThread:withObject:waitUntilDone:.
Related: Is it possible to associate a dispatch queue with a certain background thread, just like the main queue is associated with the application's main thread?
Edit Clarified that I am looking to run an anonymous block

I saw this function RunOnThread() recently in Mike Ash's PLBlocksPlayground (zip file, see BlocksAdditions.m):
void RunOnThread(NSThread *thread, BOOL wait, BasicBlock block)
{
[[[block copy] autorelease] performSelector: #selector(my_callBlock) onThread: thread withObject: nil waitUntilDone: wait];
}
This is what I was looking for.
There are a bunch of other very useful blocks related utilities in PLBlocksPlayground, most of which Mr. Ash explains in this post.

If I understand you right you should do this:
dispatch_queue_t thread = dispatch_queue_create("your dispatch name", NULL);
dispatch_async(analyze, ^{
//code of your anonymous block
});
dispatch_release(thread);
You also can write some method, which will take block to it, but you should know what type of parameters will it holds:
-(void)performBlock:(void (^)(SomeType par1, SomeType par2))block ToData:(Sometype)data;
You can call it with anonymous block:
[something performBlock:^(SomeType par1, SomeType par2){
//do your stuff
} ToData: data]
And in method you can call your block as a simple C function:
block(par1, par2);

A block is a function. Call it like you would call any other function.

Related

Run C function in background in Objective-C

I want to call a C function in a Objective-C app. The function contains an endless loop. So I need to run this C function in background.
Here's my C function:
int go(){
for(;;){
//...
}
return 0;
}
And the call:
[self performSelectorInBackground:go() withObject:nil];
The function go() is called but it's not running in background (and the app stop working...).
Even in the background you probably should run something in an endless loop. However it is possible.
[self performSelectorInBackground:<selector> withObject:<Object>];
That is a nice convenience method to just throw a method to the background thread. But you also have access to Grand Central Dispatch that would let you put blocks of code into a background thread as well. You could even give it a private queue so it wouldn't block your background queue.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// Your code
go();
});
Hmm, there may be an easier way, but...
- (int)doGo {
return go();
}
Then...
[self performSelectorInBackground:#selector(doGo) withObject:nil];
So, this answer really just highlights what I believe is the most fundamental problem with your provided code, but you should certainly see Ryan's answer and use GCD. performSelectorInBackground: really isn't all that great.

Does #synchronized block a whole thread

Say you do
MyLock *lock = [[MyLock new] autorelease];
#synchronized(lock) {
NSLog(#"Hello World");
//some very long process
}
In the main thread. Does that mean till //some very long process is done, the main thread is locked? If some other thread call
//Update on the main thread
dispatch_sync(dispatch_get_main_queue(), ^{
//Do some updates
});
That some updates will never be called? Am I correct?
If the code in the first code snippet never finishes, the second one won't be called, regardless of the #synchronized statement. The thread is blocked by the code that you're executing. The #synchronized statement is to synchronize data access between multiple threads and to be useful, it requires that all participating threads actually use the statement. It will not "magically" lock access to the data structure, unless all participating threads "agree" on it.
You don't use #synchronized to ensure that only one method executes on a given (single) thread, that is the case anyhow.
To give you a concrete example of its use, let's say you have an NSMutableArray that you want to protect from getting modified from different threads at the same time (which could lead to data corruption). In that case, you could always access it in a #synchronized block with the same lock token.
Example:
//Thread 1:
#synchronized (myArray) {
[myArray addObject:#"foo"];
}
//Thread 2:
#synchronized (myArray) {
[myArray removeObjectAtIndex:0];
}
This will ensure that the blocks of code that are enclosed by the #synchronized will never execute simultaneously. When one thread enters the block, other threads wait until it finishes, but only if they also use the same #synchronized statement. If you forget to use it on one thread, it doesn't help at all if you used it on the other.
The short answer is no. I think you dont understand the concept of locking. You should read more about syncchronization for example here:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html
You have to synchronize using the same locking object (same instance!) in every case when you access the code, which you are trying to protect. You can store the locking object as property of a class.
In your case:
self.lock = [[MyLock new] autorelease]; //in init method initialize retain or strong lock property
...
#synchronized(self.lock) {
NSLog(#"Hello World");
//some very long process
}
//Update on the main thread
dispatch_sync(dispatch_get_main_queue(), ^{
#synchronized(self.lock) {
NSLog(#"Hello World");
//some very long process
}
});
If you can use as the locking object, the object which your are trying to protect.

App stops inconsistently at a call to dispatch_sync() [duplicate]

Im using XMPPFramework and in it's code there's a method like this:
- (NSDictionary *)occupants
{
if (dispatch_get_current_queue() == moduleQueue)
{
return occupants;
}
else
{
__block NSDictionary *result;
dispatch_sync(moduleQueue, ^{//IT BLOCKS HERE, WITHOUT MESSAGE
result = [occupants copy];
});
return [result autorelease];
}
}
[EDIT]
It blocks inconsistently, not always, since the app is not doing anything I pause it and I see the thread has stopped there, and it never continues to execute.
What is wrong? Any ideas?
Thanks
The behavior you explain perfectly matches with the one that appears when you try to send perform an operation on main thread via GCD while being on the main thread. So you should check if moduleQueue is the main queue, then this is it. Try checking if it is the main queue if it is, skip the dispatch_sync block.
Blocks sometimes need to retain variables to ensure they are available when they execute. If you use a local variable inside a block, you should initialise it to zero where you declare it outside the block.

App blocks while dipatching a queue

Im using XMPPFramework and in it's code there's a method like this:
- (NSDictionary *)occupants
{
if (dispatch_get_current_queue() == moduleQueue)
{
return occupants;
}
else
{
__block NSDictionary *result;
dispatch_sync(moduleQueue, ^{//IT BLOCKS HERE, WITHOUT MESSAGE
result = [occupants copy];
});
return [result autorelease];
}
}
[EDIT]
It blocks inconsistently, not always, since the app is not doing anything I pause it and I see the thread has stopped there, and it never continues to execute.
What is wrong? Any ideas?
Thanks
The behavior you explain perfectly matches with the one that appears when you try to send perform an operation on main thread via GCD while being on the main thread. So you should check if moduleQueue is the main queue, then this is it. Try checking if it is the main queue if it is, skip the dispatch_sync block.
Blocks sometimes need to retain variables to ensure they are available when they execute. If you use a local variable inside a block, you should initialise it to zero where you declare it outside the block.

Objective C send message to creator

I don't quite understand about how to deal with next kind of task:
#implementation SomeInterface
-(void)DoSomething
{
MyObj * mo = [MyObj new];
[mo doJob];
}
end
The question is - how can mo send message back to SomeInterface after doJob is finished?
Should I use NSNotificationCenter?
As of iOS 4, probably the easiest thing to do is to pass a block to doJob that dictates what it should do upon completion. So, for example...
MyObj.h:
// create a typedef for our type of completion handler, to make
// syntax cleaner elsewhere
typedef void (^MyObjDoJobCompletionHandler)(void);
#interface MyObj
- (void)doJobWithCompletionHandler:(MyObjDoJobCompletionHandler)completionHandler;
#end
MyObj.m:
- (void)doJobWithCompletionHandler:(MyObjDoJobCompletionHandler)completionHandler
{
/* do job here ... */
// we're done, so give the completion handler a shout.
// We call it exactly like a C function:
completionHandler();
/* alternatives would have been to let GCD dispatch it,
but that would lead to discussion of GCD and a bunch of
thread safety issues that aren't really relevant */
}
Within SomeInterface.m:
-(void)DoSomething
{
MyObj * mo = [MyObj new];
[mo doJobWithCompletionHandler:
^() // you can omit the brackets if there are no parameters, but
// that's a special case and I don't want to complicate things...
{
NSLog(#"whoop whoop, job was done");
// do a bunch more stuff here
}
];
}
I assume that in reality you're doing something that ends up being asynchronous in DoJob (or else you'd just wait until the method returns); in that case you might want to use GCD's dispatch_async with the result of dispatch_get_main_queue to ensure the completion handler takes place back on the main thread.
Joachim Bengtsson has written a good introductory guide to blocks. As to how they interact with Grand Central Dispatch (and how to use GCD in general), Apple's documentation is good.
yes, you can use NSNotificationCenter or write callback method