I am currently learning IOS Threading programming... I encountered an issue:
Here comes my code, please kindly have a look:
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSThread *t1 = [[NSThread alloc]initWithTarget:[MyThread class] selector:#selector(myMethod:) object:Nil];
[t1 start];
}
return 0;
}
#import "MyThread.h"
#implementation MyThread
+ (void)myMethod:(id)param
{
#autoreleasepool {
NSLog(#"called...");
}
}
#end
However, when I ran my program, though there was no error, no message was printed on the console. It seems like myMethod was not executed. I wonder if anyone could give me some suggestions. It has already driven me crazy.
Many thanks in advance.
The main thread of your application is exiting before your other thread has a chance to process anything.
It will work if you add in a simple sleep(1000) statement anywhere before the return 0 statement in your main method.
Your application is terminating before the thread has executed the NSLog.
NSThread creates a detached thread, see Apple's Thread Programming Guide, from which comes:
Important: At application exit time, detached threads can be terminated immediately but joinable threads cannot. Each joinable thread must be joined before the process is allowed to exit. Joinable threads may therefore be preferable in cases where the thread is doing critical work that should not be interrupted, such as saving data to disk.
To create a joinable thread, and hence be able to block your main thread until all joinable threads have finished, you use pthread - covered in the above Guide.
The Java thread model is similar, but uses slightly different terminology. By default a Java thread is joinable and the Java application will continue to execute until all such threads have terminated. A Java thread can be converted to a daemon thread, which is automatically terminated on application exit as with NSThread threads.
Related
When learning thread and run loop, I notice that some articles say: "Generally, a thread just exits once it has done its work." So there is necessity sometimes to create a so-called "immortal thread"(?? I don't know the exact term in English) using NSRunloop.
The question is HOW can I prove the statement "just exits once it has done its work"? I code like this
- (void)doSomethingOnThread {
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// NSLog(#"I'm on thread %#", [NSThread currentThread]);
// });
NSThread *thread1 = [[NSThread alloc] initWithBlock:^{
NSLog(#"I'm on thread %#", [NSThread currentThread]);
}];
thread1.name = #"thread1";
[thread1 start];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(threadExitHandler:) name:NSThreadWillExitNotification object:nil];
}
- (void)threadExitHandler:(NSNotification *)noti {
NSLog(#"Thread will exit: %#", noti);
}
Well, the notification handler is not called.
So, [1]: How can I prove a thread exiting? [2]: What kinds of threads behave so?(I know the main thread will never exit, what about other thread? GCD threads, for example?)
If you want to visualize it, I might use the debugger. For example, I've set a breakpoint inside a NSThread subclass and I see the thread listed in the left panel in Xcode:
But if I have another breakpoint triggered one second after the main method finishes, I see the relevant “Thread will exit” message and my thread is no longer present :
Or you could add a NSLog statement inside the dealloc method for your NSThread subclass, and that also would demonstrate its deallocation. Or look for the subclass in the debug memory object graph.
Well, the notification handler is not called.
I'd suggest you add your observer for NSThreadWillExitNotification before you start your thread. Right now you have a race condition between the starting and exiting of this thread and the adding of the observer. FWIW, I do see the “Thread will exit” message.
Unrelated, while it’s great to learn about threads and runloops, it has little practical use nowadays. It might be more useful to master GCD which gets us out of the weeds of threads and offers performance optimizations and a richer API for writing robust multi-threaded code.
In regards to whether GCD creates persistent threads or not, the answer is yes, but we're abstracted away from this detail. But one of GCD’s performance optimizations is that it manages a “pool” of threads for us, not constantly spinning up new threads and destroying them constantly for every dispatched block of code.
You might want to watch WWDC 2016’s Concurrent Programming With GCD in Swift 3. It walks through the relationship between queues, threads, and runloops.
im developing an app, which uses some framework to draw 3D staff via openGL. This framework requires me to call draw() method from exact the same Thread.
So i created a serial DispatchQueue and started CADisplayLink in it, calling draw() at 60FPS. There are few other methods that i have to call from this exact thread, like start() and stop(). This makes queues perfect solution to me.
As you may know DispathQueue does not guaranteed to execute every task on the same thread. Which is quite stressful for me, as it may break my app.
I don't really like the idea to create NSThread and implement my own queue on it.
Are there any way to bind DispatchQueue to exact Thread? Maybe NSOperationQueue can be bound?
As Apple Documentation says:
When it comes to adding concurrency to an application, dispatch queues provide several advantages over threads. The most direct advantage is the simplicity of the work-queue programming model. With threads, you have to write code both for the work you want to perform and for the creation and management of the threads themselves. Dispatch queues let you focus on the work you actually want to perform without having to worry about the thread creation and management. Instead, the system handles all of the thread creation and management for you. The advantage is that the system is able to manage threads much more efficiently than any single application ever could. The system can scale the number of threads dynamically based on the available resources and current system conditions. In addition, the system is usually able to start running your task more quickly than you could if you created the thread yourself.
In simple words, you either work with dispatch queues, simply creating them and sending work to them, OR you work with NSThreads and NSRunLoops, creating them, setting them up, sending work to them, and possibly stopping them.
In detail:
NSThread / NSRunLoop
Creation:
self.thread = [[NSThread alloc] initWithTarget:self selector:#selector(threadMainRoutine) object:nil];
[self.thread start];
Start / management:
- (void)threadMainRoutine
{
// Set the runLoop variable, to signal this thread is alive
self.runLoop = [NSRunLoop currentRunLoop];
// Add a fake Mach port to the Run Loop, to avoid useless iterations of the main loop when the
// thread is just started (at this time there are no events added to the run loop, so it will
// exit immediately from its run() method)
[self.runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
//--- Thread main loop
while (thread_KeepRunning)
{
// Run the run loop. This function returns immediately if the RunLoop has nothing to do.
// NOTE: THIS STATEMENT:
// [self.runLoop run];
// DOES NOT WORK, although it is equivalent to CFRunLoopRun();
CFRunLoopRun();
}
// Unset the runLoop variable, to signal this thread is about to exit
self.runLoop = nil;
}
Adding work to be performed on it:
[self performSelector:#selector(mySelector:) onThread:myThread withObject:myObject waitUntilDone:YES];
Shutdown:
- (void)stop
{
if (self.thread) {
while (self.thread.isExecuting) {
thread_KeepRunning = NO;
CFRunLoopStop([self.runLoop getCFRunLoop]);
[NSThread sleepForTimeInterval:0.1f];
}
}
self.runLoop = nil;
self.thread = nil;
}
Dispatch Queue
Creation:
dispatch_queue_t myQueue = dispatch_queue_create("My Queue", DISPATCH_QUEUE_SERIAL);
Start:
dispatch_resume(myQueue);
Adding work to be performed on it:
dispatch_async(myQueue, (void)^ {
// put the work into this block
});
Shutdown:
dispatch_suspend(myQueue);
myQueue = nil;
In addition, Apple Documentation says that
Because Grand Central Dispatch manages the relationship between the tasks you provide and the threads on which those tasks run, you should generally avoid calling POSIX thread routines from your task code. If you do need to call them for some reason, you should be very careful about which routines you call
So: if you use dispatch queues, don't mess with threads.
I am having UI frozen/blocked due to semaphore_wait_trap in main thread.
When the UI is frozen, I pause using XCODE and the last two lines in stacktrace:
0x103f0ea30 <+809>: callq 0x103f1554d ; _dispatch_thread_semaphore_wait
dispatch_sync(someQueue, block); // this is my code.
How can I find what is causing the block?
Any other suggestion to find out what is causing the block?
It always blocks on the same line/code.
In the Debug navigator (cmd-6), you should have a list of threads. One OTHER thread in there should be waiting for someQueue as well. I can't think off hand of a case where that wasn't the case. Usually the two threads are waiting for each other, (e.g. via dispatch_sync).
For example, you might have this:
dispatch_sync(mySerialQueue, ^{
[self foo];
});
and
- (void)foo
{
dispatch_sync(mySerialQueue, ^{
...
});
}
The latter will be waiting for the former to finish forever, because the former is holding onto myQueue until it finishes the call to -foo.
(Note that mySerialQueue has to be created with the DISPATCH_QUEUE_SERIAL for this to happen.)
I have a long running function inside an asynchronous (serial) worker queue.
I know that sometimes this function hangs inside a particular openCV call.
For some reason this hang is also causing the main thread to hang.
When pausing and entering debug mode I see that there is a call to
semaphore_wait_trap()
on the main thread (Queue)
I can suspend the hanging thread (My worker queue) in debug mode and then this trap goes away and the GUI becomes responsive once again on the phone.
After unpausing the worker thread the GUI is responsive for 1-2 seconds (I suspect until this thread is activated again) and then the UI becomes unresponsive once again.
This thread makes no dispatch_sync() calls to the main thread/Queue
Is it possible that IOS pauses the main thread ("traps" it) because the worker is long running?
Can I force it to remove the block??
I am adding some print screens of the debug mode stack.
Before suspending the hanging Queue:
And the hanging thread:
And After Pausing and suspending the bad queue:
Is it possible that IOS pauses the main thread ("traps" it) because the worker is long running? - NO.
I think, your problem is related to drawing or changing some UI elements. Not all functions can be called from background thread (e.g. changes to UI elements has to be done in main thread.). In your serial queue, if any method needs to change UI elements, you have to call it on main thread e.g
dispatch_async(dispatch_get_main_queue(), ^{
//do some main thread job here
});
)
Maybe you just forgot to retain a variable into dispatch function call (As for me I was omitted a static keyword before dispatch_once_t declaration and dispatch can't process with inline function). The stack trace was just like yours. That was my fault.
+ (instancetype)sharedInstance
{
(static was omitted) dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
I've started experimenting with POSix threads using the ios platform. Coming fro using NSThread it's pretty daunting.
Basically in my sample app I have a big array filled with type mystruct. Every so often (very frequently) I want to perform a task with the contents of one of these structs in the background so I pass it to detachnewthread to kick things off.
I think I have the basics down but Id like to get a professional opinion before I attempt to move on to more complicated stuff.
Does what I have here seem "o.k" and could you point out anything missing that could cause problems? Can you spot any memory management issues etc....
struct mystruct
{
pthread thread;
int a;
long c;
}
void detachnewthread(mystruct *str)
{
// pthread_t thread;
if(str)
{
int rc;
// printf("In detachnewthread: creating thread %d\n", str->soundid);
rc = pthread_create(&str->thread, NULL, DoStuffWithMyStruct, (void *)str);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
//exit(-1);
}
}
//
/* Last thing that main() should do */
// pthread_exit(NULL);
}
void *DoStuffWithMyStruct(void *threadid)
{
mystruct *sptr;
dptr = (mystruct *)threadid;
// do stuff with data in my struct
pthread_detach(soundptr->thread);
}
One potential issue would be how the storage for the passed in structure mystruct is created. The lifetime of that variable is very critical to its usage in the thread. For example, if the caller of detachnewthread had that declared on the stack and then returned before the thread finished, it would be undefined behavior. Likewise, if it were dynamically allocated, then it is necessary to make sure it is not freed before the thread is finished.
In response to the comment/question: The necessity of some kind of mutex depends on the usage. For the sake of discussion, I will assume it is dynamically allocated. If the calling thread fills in the contents of the structure prior to creating the "child" thread and can guarantee that it will not be freed until after the child thread exits, and the subsequent access is read/only, then you would not need a mutex to protect it. I can imagine that type of scenario if the structure contains information that the child thread needs for completing its task.
If, however, more than one thread will be accessing the contents of the structure and one or more threads will be changing the data (writing to the structure), then you probably do need a mutex to protect it.
Try using Apple's Grand Central Dispatch (GCD) which will manage the threads for you. GCD provides the capability to dispatch work, via blocks, to various queues that are managed by the system. Some of the queue types are concurrent, serial, and of course the main queue where the UI runs. Based upon the CPU resources at hand, the system will manage the queues and necessary threads to get the work done. A simple example, which shows the how you can nest calls to different queues is like this:
__block MYClass *blockSelf=self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[blockSelf doSomeWork];
dispatch_async(dispatch_get_main_queue(), ^{
[blockSelf.textField setStringValue:#"Some work is done, updating UI"];
});
});
__block MyClass *blockSelf=self is used simply to avoid retain cycles associated with how blocks work.
Apple's docs:
http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html
Mike Ash's Q&A blog post:
http://mikeash.com/pyblog/friday-qa-2009-08-28-intro-to-grand-central-dispatch-part-i-basics-and-dispatch-queues.html