NSThread issue how to resolve? - objective-c

I m writting the following code.
#import <objc/objc.h>
#import <Foundation/Foundation.h>
#interface myT :NSObject
-(void) startT;
-(void) tfun;
#end
#implementation myT
-(void) tfun
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog (#"Inside thread Function .. ");
[pool drain];
}
-(void) startT
{
[NSThread detachNewThreadSelector:#selector(tfun) toTarget:self withObject:nil ];
}
#end
int main ( int argc, char ** argv)
{
myT *t = [[myT alloc] init];
[t startT];
return 0;
}
it compiles, and leads to run time error. what i am doing wrong ? i am familiar with pthread. how can i wait till the thread completes, ie: pthread_wait kind.

You can spin the run loop until you set a complete flag like:
-(void) startT
{
[NSThread detachNewThreadSelector:#selector(tfun) toTarget:self withObject:nil ];
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!self.completed);
}
And in your tfun method
-(void) tfun
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog (#"Inside thread Function .. ");
[pool drain];
self.complete = YES;
}

Related

iOS NSObject nil after initialisation in block

I have an NSObject that I create inside a block. As per the code below:
__block NSObject *myObject;
[self myMethod:^{
myObject = [[NSObject alloc] init];
....
}];
if(myObject == nil){
NSLog(#"Why is my object nil?!");
}
In the definition of myMethod I have the following:
backgroundQueue = dispatch_queue_create("backgroundqueue", NULL);
dispatch_async(backgroundQueue,
^{
dispatch_async(dispatch_get_main_queue(),
^{
if(block){
block();//Never called.
}
});
However the block is never called.
The problem here is that you never seem to execute the block in which you instantiate myObject. For illustration, run this little program:
#import <Foundation/Foundation.h>
typedef void(^MyTestBlock)(void);
#interface Foo:NSObject
- (id)initWithBlock:(MyTestBlock)aBlock;
- (void)someMethod;
#end
#implementation Foo {
MyTestBlock _block;
}
- (id)initWithBlock:(MyTestBlock)aBlock {
self = [super init];
if( !self ) { return nil; }
_block = aBlock;
return self;
}
- (void)someMethod {
_block();
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
__block NSObject *myObject;
Foo *myFoo = [[Foo alloc] initWithBlock:^{
myObject = [[NSObject alloc] init];
}];
[myFoo someMethod];
NSLog((myObject)?#"Your object was created":#"Why is my object nil?");
}
}
This prints 2012-11-26 05:00:58.519 Untitled 2[23467:707] Your object was created to the console. The point is that blocks don't execute themselves. In the code above, although we set the block as an ivar of the class, we don't execute it until we call someMethod on our Foo.
EDIT:
An edit to your question states that the block is not executed in the context of an asynchronous dispatch block sent to the main queue. If this is a command line application, then you must call dispatch_main() at the end of main. See the man page for dispatch_get_main_queue(). Here is a full working command line application to illustrate this, as well as issues related to race conditions:
#import <Foundation/Foundation.h>
typedef void(^MyTestBlock)(void);
#interface Foo:NSObject
- (id)initWithBlock:(MyTestBlock)aBlock;
- (void)someMethod;
#end
#implementation Foo {
MyTestBlock _block;
}
- (id)initWithBlock:(MyTestBlock)aBlock {
self = [super init];
if( !self ) { return nil; }
_block = aBlock;
return self;
}
- (void)someMethod {
dispatch_queue_t backgroundQueue = dispatch_queue_create("backgroundqueue", NULL);
dispatch_async(backgroundQueue, ^{
dispatch_queue_t innerQueue = dispatch_get_main_queue();
dispatch_async(innerQueue, ^{
if( _block){
NSLog(#"Will call block.");
_block();
}
});
});
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
__block NSObject *myObject;
Foo *myFoo = [[Foo alloc] initWithBlock:^{
myObject = [[NSObject alloc] init];
}];
[myFoo someMethod];
// this log statement should show that myObject is nil because it will (probably)
// be executed before your block.
NSLog((myObject)?#"Your object was created":#"Why is my object nil?");
// wait a little bit to resolve race condition (just for illustrative purposes)
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.4f * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
NSLog((myObject)?#"Your object was created":#"Why is my object nil?");
});
}
// this isn't a Cocoa app, so must call dispatch_main() at end of main
dispatch_main();
}
You have forgotten to call your block in your myMethod. Try the code bellow.
typedef void(^MyBlock)();
- (void)myMethod:(MyBlock)aBlock
{
aBlock();
}

What is the meaning of using combination of detachNewThreadSelector:toTarget:withObject and [NSThread Start]

I am using below code where in method startThread if I am using detachNewThreadSelector method, it blocks my UI but when I use to make object of NSThread and call start method and in that I called run method it is not blocking my UI.
What I am not getting is detachNewThreadSelector will run in background so it should not block my UI.then why so in my case?
and what is with start method and NSThread object? will it run in background or main thread?
I have search so many articles and StackOverFlow questions but not get in which senario actually these Threads workout
-(void)startThread
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//NSThread *myThread = [[NSThread alloc] initWithTarget:self selector:#selector(run:) object:nil];
//[myThread start];
[NSThread detachNewThreadSelector:#selector(run:) toTarget:self withObject:nil];
[pool release];
}
-(void)run:(id)param
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
while (threadProgressView.progress < 1) {
[NSThread sleepForTimeInterval:0.25];
[self updateProgressBar];
//[NSThread detachNewThreadSelector:#selector(updateProgressBar) toTarget:self withObject:nil];
}
threadStartButton.hidden = NO;
[pool release];
}
-(void)updateProgressBar
{
NSLog(#"In update progress bar");
float actual = [threadProgressView progress];
threadValueLabel.text = [NSString stringWithFormat:#"%.2f",actual];
threadProgressView.progress = actual + 0.025;
}

NSLog: Thread Error

Error in NSLog:
*** -[NSThread initWithTarget:selector:object:]: target does not implement selector (*** -[Document myTcpClient])
code:
-(void) myTcpStart: (NSButton*) button{
//need threads for the following
thread_Client = [[NSThread alloc] initWithTarget:self selector:#selector(myTcpClient) object:nil];
thread_Display = [[NSThread alloc] initWithTarget:self selector:#selector(displayData) object:nil];
[thread_Client start];
[thread_Display start];
[textField1 setStringValue:#"waiting for threads to run"];
}
-(void) myTcpStop: (NSButton*) button{
//need threads for the following
//[thread_Client cancel];
//[thread_Display cancel];
}
-(void) displayData{
while(1){
[textField1 setStringValue:[NSString stringWithFormat:#"%d %d %f", j, i, genValue]];
j++;
}
}
-(void) myTcpClien{
//some code
}
header file:
#import <Cocoa/Cocoa.h>
#interface Document : NSDocument
{
NSTextField *textField1;
int i;
int j;
double genValue;
NSWindowController *bController;
NSThread *thread_Client;
NSThread *thread_Display;
}
-(void) myTcpClient;
-(void) displayData;
-(void) myTcpStart: (NSButton*) button;
-(void) myTcpStop: (NSButton*) button;
#end
You forgot the T in myTcpClient implementation. Again when you see these messages check your code for spelling errors.
Change:
- (void)myTcpClien { /* ... */ }
To:
- (void)myTcpClient { /* ... */ }

NSCondition ->Objective C

I am a newbie to Objective-C. I'm currently working on threads.
I have to make a synchronous execution of threads. I'm using NSInvocationOperaion to spawn a thread.
I have two threads. I need to wait for the 1st thread to signal a event or the timeout.
Signalling a event can be done by NSConditionLock. How to signal a timeout. I could not use waitUntilDate method here as the timeout is not a fixed value.
Is there any way to do this?
EDITED
main.m
------
#import "PseudoSerialQueue.h"
#import "PseudoTask.h"
int main()
{
PseudoSerialQueue* q = [[[PseudoSerialQueue alloc] init] autorelease];
[q addTask:self selector:#selector(test0)];
[q addTask:self selector:#selector(test1)];
[q addTask:self selector:#selector(test2)];
[q quit];
return 0;
}
PseudoTask.h
-----------------
#import <Foundation/Foundation.h>
#interface PseudoTask : NSObject {
id target_;
SEL selector_;
id queue_;
}
#property(nonatomic,readonly)id target;
-(id)initWithTarget:(id)target selector:(SEL)selector queue:(id)queue;
-(void)exec;
#end
PseudoTask.m
-----------------
#import "PseudoTask.h"
#implementation PseudoTask
#synthesize target = target_;
-(id)initWithTarget:(id)target selector:(SEL)selector queue:(id)queue
{
self = [super init];
if (self) {
target_ = [target retain];
selector_ = selector;
queue_ = [queue retain];
}
return self;
}
-(void)exec
{
[target_ performSelector:selector_];
}
-(void)dealloc
{
[super dealloc];
[target_ release];
[queue_ release];
}
#end
PseudoSerialQueue.h
----------------------------
#import <Foundation/Foundation.h>
#import "PseudoTask.h"
#interface PseudoSerialQueue : NSObject {
NSCondition* condition_;
NSMutableArray* array_;
NSThread* thread_;
}
-(void)addTask:(id)target selector:(SEL)selector;
#end
PseudoSerialQueue.m
----------------------------
#import "PseudoSerialQueue.h"
#implementation PseudoSerialQueue
-(id)init
{
self = [super init];
if (self) {
array_ = [[NSMutableArray alloc]init];
condition_ = [[NSCondition alloc]init];
thread_ = [[NSThread alloc] initWithTarget:self selector:#selector(execQueue) object:nil];
[thread_ start];
}
return self;
}
-(void)addTask:(id)target selector:(SEL)selector
{
[condition_ lock];
PseudoTask* task = [[PseudoTask alloc] initWithTarget:target selector:selector queue:self];
[array_ addObject:task];
[condition_ signal];
[condition_ unlock];
}
-(void)quit
{
[self addTask:nil selector:nil];
}
-(void)execQueue
{
for(;;)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc]init];
[condition_ lock];
if (array_.count == 0) {
[condition_ wait];
}
PseudoTask* task = [array_ objectAtIndex:0];
[array_ removeObjectAtIndex:0];
[condition_ unlock];
if (!task.target) {
[pool drain];
break;
}
[task exec];
[task release];
[pool drain];
}
}
-(void)dealloc
{
[array_ release];
[condition_ release];
[super dealloc];
}
#end
I could not pass self from main.Hope i'm mistakenly calling it.
Error:'self' undeclared is coming.
I could not understand
-(void)exec
{
[target_ performSelector:selector_];
}
in PseudoTask.m
target_ is not a method and its an ivar.
I am not getting any error or warning.But i could not understand that code.
I am writing what i have understood from your program.Please correct me if i my way of understanding the program is wrong.
The Thread execQueue is spawned when the PseudoSerialQueue is initialised and it waits for the signal from the addTask method.
The addTask method is called in the quit method and the parameters passed are nil.I could not understand why to pass a nil parameter.
It would be helpful if you explain about it.Thanks.
You mean NSCondition? You can use waitUntilDate: as relative time.
[condition lock];
// wait 5 seconds.
[condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:5]];
[condition unlock];
EDITED:
My PseudoSerialQueue class requires to be called from a class that is derived from NSObject like the following.
#interface Test : NSObject
#end
#implementation Test
- (void)test0
{
}
- (void)test1
{
}
- (id)init
{
self = [super init];
return self;
}
- (void)exec
{
PseudoSerialQueue *q = [[PseudoSerialQueue alloc] init];
[q addTask:self selector:#selector(test0)];
[q addTask:self selector:#selector(test1)];
[q addTask:self selector:#selector(test0)];
[q quit];
}
#end
You can call it from main function.
Test *test = [[Test alloc] init];
[test exec];
I could not understand why to pass a nil parameter.
I just only chose it for the message of quitting the loop in the PseudoSerialQueue.
Let the 1st thread signal the 2nd one in both cases; then in the second thread you can tell in which case you are based on some read-only flag in the 1st controller or in your model (say, isDataAvailable).

asynchronous call using the NSOperationQueue

I am a beginner in developing iPhone applications.
I was doing this sample program below and got an error- invalid use of void expression
threadsss.h
------------
#import <Foundation/Foundation.h>
#interface threadsss : NSObject {
BOOL m_bRunThread;
int a,b,c;
}
-(void)Thread;
-(void)add;
-(void)display;
#end
threadsss.m
------------
#import "threadsss.h"
#implementation threadsss
-(void)Thread
{
m_bRunThread = YES;
NSOperationQueue* queue = [[NSOperationQueue alloc]init];
NSInvocationOperation* operation = [[NSInvocationOperation alloc]initWithTarget:self selector:#selector(display) object:nil];
[operation addDependency:[self add]];
[queue addOperation:operation];
[queue release];
}
-(void)add
{
NSLog(#"Going to add a and b!!");
a=1;
b=2;
c = a + b;
NSLog(#"Finished adding!!");
}
-(void)display
{
NSLog(#"Into the display method");
NSLog(#"The value od c is:%d",c);
}
#end
main.m
-------
#import <Foundation/Foundation.h>
#import "threadsss.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
threadsss* thread = [[threadss alloc]init];
[thread Thread];
[pool drain];
return 0;
}
I want to make an asynchronous call between the add and the display methods.After calling the display method i want to execute the add method. and in the meanwhile after printing the "I'm into the display method" the display method will wait for the add to perform its operation and the add after doing its operation will notify its completion to the display method.The display method will then print the result c.
I have tried to implement it with that in my mind.Do i need to do any other modification in my program or is the way i have implemented through dependecies is correct.
EDITED
threadss.h
-----------
#import <Foundation/Foundation.h>
#interface threadss : NSObject {
BOOL m_bRunThread;
int a,b,c;
NSOperationQueue* queue;
NSInvocationOperation* operation;
NSInvocationOperation* operation1;
NSConditionLock* theConditionLock;
}
-(void)Thread;
-(void)add;
-(void)display;
#end
threadss.m
-----------
#import "threadss.h"
#implementation threadss
-(id)init
{
if (self = [super init]) {
queue = [[NSOperationQueue alloc]init];
operation = [[NSInvocationOperation alloc]initWithTarget:self selector:#selector(display) object:nil];
operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:#selector(add) object:nil];
theConditionLock = [[NSConditionLock alloc]init];
}
return self;
}
-(void)Thread
{
m_bRunThread = YES;
//[operation addDependency:operation1];
if (m_bRunThread) {
[queue addOperation:operation];
}
//[operation addDependency:operation1];
[queue addOperation:operation1];
//[self performSelectorOnMainThread:#selector(display) withObject:nil waitUntilDone:YES];
//NSLog(#"I'm going to do the asynchronous communication btwn the threads!!");
//[self add];
//[operation addDependency:self];
sleep(1);
[queue release];
[operation release];
//[operation1 release];
}
-(void)add
{
NSLog(#"Going to add a and b!!");
a=1;
b=2;
c = a + b;
NSLog(#"Finished adding!!");
}
-(void)display
{
NSLog(#"Into the display method");
[operation1 waitUntilFinished];
NSLog(#"The Result is:%d",c);
}
#end
main.m
------
#import <Foundation/Foundation.h>
#import "threadss.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
threadss* thread = [[threadss alloc]init];
[thread Thread];
[pool drain];
return 0;
}
I made two operation queues.
But using waitUntilFinished on the same queue may lead to deadlock.How do i do the wait in display method for the add operation to complete its execution.
First, it would be easier to answer your question if you identified the line than the compiler was complaining about and showing only the relevant code. However, in this case it's pretty straight-forward. It's this line:
[operation addDependency:[self add]];
The add method returns nothing (void). And you're telling operation to add that as a dependency. What does that mean?
Either, you should change add to return self or call add on the line before:
[self add];
[operation addDependency:self];