1

I have a thread call in objective C and i want once this thread ends i want to return a value ;the value will be changed inside the thread So the method must not return the value unless the tread ends

Here is the code i use:

[NSThread detachNewThreadSelector:@selector(CheckBeforePrint2) toTarget:self withObject:nil];

This is My Full Code

- (NSString *) getStatusPrinter:(NSString *) printerSerialNumber
{
    self.printerSN = printerSerialNumber;
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSString *Result = @"-1";
    [NSThread sleepForTimeInterval:2.0f];       

    [NSThread detachNewThreadSelector:@selector(CheckBeforePrint) toTarget:self withObject:Result];

    [pool release];
    return  Result;
}

Now i want to wait for the value of Result and return it i am using

cocoa

And i am returning the value to another app

Can anyone help in that.

Thanks

Sham Dhiman
  • 1,348
  • 1
  • 21
  • 59
user1992910
  • 73
  • 3
  • 11
  • I think you can use delegate to achive that. A delegate allows one object to send messages to another object when an event happens – Jian Zhong Dec 16 '18 at 11:32
  • @JianZhong using a delegate is possible but redundant because the method `CheckBeforePrint2 ` is within the same class. Definitely sounds like an anti-pattern. – pnizzle Dec 16 '18 at 23:34
  • In response to the updated code, there is still no need to create a new thread for `CheckBeforePrint` if the parent thread is going to have to wait anyway. Why do you think you need to run `CheckBeforePrint` in its own thread? – pnizzle Dec 18 '18 at 04:58
  • The last part of your question regrading sending the result to another app is another story. You can post that in a separate question (I'm sure that challenge has been answered already here on stack, unless you have a very specific problem on that) – pnizzle Dec 18 '18 at 05:04
  • I am unable to initiate a chat with you unfortunately. Because of low points probably. But have a look at the link in my answer on `openURL completion:`. That should remove the need for waiting and locking jibber jabber. Cheers – pnizzle Dec 18 '18 at 06:05

1 Answers1

4

What you are doing here requires the use of a semaphore for example. If there is nothing more to it than you are providing here then a completion block to a background running method is the best way to do it. See option 2 below

Either way, why do you want the parent thread (the thread dispatching a new thread) to wait for another thread? If the parent thread is waiting, it is locked until the dispatched thread is done (according to your requirement). This situation is redundant because the whole point of dispatching another thread is so that the parent thread can continue with other things. Unless of course the parent thread needs to wait for multiple threads, then it makes sense to lock it.

Having said that, its best to just let the dispatching thread / parent thread do the processing that you are dispatching on to another thread. Im only saying this given the details you have provided.

  • OPTION 1 use a semaphore

Use a semaphore to lock and unlock parent thread

-(void)getStatusPrinter()
{   
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    [NSThread detachNewThreadSelector:@selector(checkBeforePrint2) toTarget:self withObject: semaphore];
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    [self print]; // this will run after semaphore is unlocked
}

-(void)checkBeforePrint2:(dispatch_semaphore_t)sem
{
    //this is within child thread
    //do some processing,
    dispatch_semaphore_signal(sem);//unlock semaphore
}

But, as I mentioned before, this situation seems redundant because the parent thread waits (therefore unusable) for child thread; why can't it just do the work itself...


  • OPTION 2 use completion block (PREFERABLE)

Use a completion block that you pass to the child thread. This allows the parent thread to continue. If it is the main thread it remains free for UI stuff.

-(void)getStatusPrinter()
{   
    [self checkBeforePrint2WithCompletion: ^{
        [self print];
    }];
    //continue with more stuff
}

-(void)checkBeforePrint2WithCompletion:(void (^ __nullable)(void))completion
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //do something before executing completion code

        if(completion){
            completion();
        }
    });
}

Disclaimer: there may be typos in this code as it was not written in an editor/ IDE. Please comment if any.


  • UPDATE in response to added details.

Okay, for the fact that you said you need to return the result to another application, that means the entry thread at getStatusPrinter can not be allowed to return after dispatching a new thread. If you really need to create a new thread for CheckBeforePrint then the entry thread has to wait. That to me is pointless. You can simply run everything on the entry thread.

If you are using openURL:options:completionHandler: then the entry thread doesn't need to wait. The value of result can be passed back within the completion block.

Please refer to Apple's documentation on openURL with a completion handle

pnizzle
  • 6,243
  • 4
  • 52
  • 81
  • Hi Thanks for the answer This is my Code – user1992910 Dec 18 '18 at 04:41
  • @user1992910 what do you mean by `this is my code`? – pnizzle Dec 18 '18 at 04:45
  • @user1992910 oh okay. Like I mentioned, why can't you just do `[self CheckBeforePrint: result]` without creating a new thread? The thread running `myMethod` has to wait for the result anyway. So why do you need a separate thread for CheckBeforePrint ? – pnizzle Dec 18 '18 at 04:54
  • iam creating a plugin thats will be used in adobe flex to print using cocoa when i did what u mentioned the plugin just hang up i dont know why so the only thing worked was to create a thread but i faced a problem is that i want to get the result and return it to the plugin so that what i asked by the way i tried u first solution but also the plugin hang up – user1992910 Dec 18 '18 at 05:15
  • @user1992910 with the first solution, I fixed it earlier today. The order of events was wrong. If you try it now it should work definitely (its the same as sleeping the thread, but the thread is awaked by the other thread when its done). – pnizzle Dec 18 '18 at 05:22