How can we stop thread - ios

I am developing application in which my thread is starting when connectionDidFinishLoading.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[downloadingthread cancel];
downloadingthread = [[NSThread alloc]initWithTarget:self selector:#selector(startusingthread) object:nil];
[downloadingthread start];
}
connectionDidFinishLoading is called multiple times, so I want to stop download thread and then start agin it again. I am trying to execute last thread only. Please help me to stop my thread in between.

Never stop a thread by force.
You stop the request using -[NSURLConnection cancel].
Your thread should be on a run loop, so you would cancel the run loop for that thread if you are aborting the request but... it's very expensive to create threads all over the place, and there is often a better alternative to this problem.

Related

How can I "visualize"(observe) a thread exiting in iOS?

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.

DispatchQueue bound to exact Thread

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.

iOS, how to restart NSThread?

To restart the NSSthread, I'm using the code below:
- (IBAction)listen:(id)sender {
thread = [[NSThread alloc] initWithTarget:self selector:#selector(listen1) object:nil];
[thread start];
[thread cancel];
[thread start];
}
But when I built and pressed this button, I've received error: "attempt to start the thread again"
Can you help me?
Method -cancel doesn't stop the thread, it just sets cancel flag.
Changes the cancelled state of the receiver to indicate that it should exit.
- (void)cancel
The semantics of this method are the same as those used for the NSOperation object. This method sets state information in the receiver that is then reflected by the isCancelled method. Threads that support cancellation should periodically call the isCancelled method to determine if the thread has in fact been cancelled, and exit if it has been.
You can stop a Thread only from within itself by calling [NSThread exit].
By the way, what are you trying to achieve? Starting separate thread is almost never good idea and starting the same thread twice is twice wrong.

dispatch_async block on main queue is never execeuted

I have an app that uses a connection queue that handles the connections on a background thread. Each connection sends a JSON post, then when it receives a success, saves some objects into coredata.
Once all connections are complete, i call a dispatch_async on the main thread to call a finished method.
However, under very specific conditions of data im sending/saving, I've noticed the dispatch_async block to the main thread never gets called, and the app screen freezes, all execution stops, and the app sits idle with a frozen screen. processing power according to xcode is 0%.
Here is method with the block that fails.
- (void)connectionDidComplete
{
_completeConnections++;
_syncProgress = (float)_completeConnections / (float)_totalConnections;
dispatch_async(mainQueue, ^(void) {
[[NSNotificationCenter defaultCenter] postNotificationName:SyncQueueDidUpdateNotification object:nil];
}); <-- this dispatch works
if (_completeConnections == _totalConnections)
{
// clear unsynced data
NSArray *syncedObjects = [SyncObject completedSyncObjects];
if (syncedObjects.count > 0)
{
for (SyncObject *syncObject in syncedObjects)
{
[syncObject delete];
}
}
//this method saves the current context, then merges this context with the main context right after
[[VS_CoreDataManager sharedManager] saveManagedObjectContextAndWait:managedObjectContext];
// cleanup the thread's context
[[VS_CoreDataManager sharedManager] unRegisterManagedObjectContextForThread:currentThread];
managedObjectContext = nil;
// complete sync
dispatch_async(mainQueue, ^(void) {
[self performSelector:#selector(finishSync) withObject:nil afterDelay:2];
}); <-- this dispatch never gets called
}
}
My suspicion is this problem has something to do with saving the context then merging it. And possibly while that is happening its released in the middle of the merge, causing some weird hang up and the dispatch isn't getting executed. This is just a guess though, and I don't know how to fix it.
Any ideas?
Thanks.
If the block on the main thread is not executed, then it is because of 1 of 2 reasons.
The main thread is blocked; is not processing any events at all. Got a while() loop on the main thread? That'd do it. A lock? There you go.
The main thread is running a modal run loop inside the outer run loop. Asynchronous dispatches to the main event loop -- main thread -- won't be processed in this case.
Set a breakpoint on that dispatch_async() and see what the main thread is doing (at the point of dispatch the main thread is most likely already in the bad state).
DarkDust's suggestion of using dispatch_after() is a good one, but is unlikely to work in that it is almost assuredly the case that your main thread is not processing events when the problem occurs. I.e. fix the problem, then move to dispatch_after() as DarkDust suggests.
If your main thread is busy with modal runloop, then you could try
CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, block
});
I believe this is a great discussion. I came across this when I had the following code:
dispatch_synch(dispatch_get_main_queue()){
print("I am here")
}
the print code did not execute as I was dispatching a 'synch' block on the serial main thread which caused a dead lock. print was waiting for the dispatch to finish and dispatch was waiting for print to finish. When you dispatch in the main serial queue then you should use dispatch_async. and i guess if you use a concurrent queue then dispatch synch suits better

Sleep or Pause NSThread

I am creating a new Thread which runs one of my method after every certain period of time.
Now what i am doing is as follows:
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:#selector(setUpTimerThread) object:nil];
[thread start];
the above method calls my setUpTimerThraed method, and this method makes an NSTimer and calls a specific method i.e syncData after every 1 minute. Now what i want is my sync Data method is sending some files to the FTP folder. and when ever it send one file to the FTP I want it my "thread" to be sleep for a while.
i have used
[NSThread sleepForTimeInterval:3.0];
But this code blocks my application main thread. Is there any way i can only sleep my "thread" thread for a while so that it wont stop my application responding for 3 seconds and does not sleep my main thread.
Hope u get what i am asking guys. PLease help?
sleepForTimeInterval: sleeps the thread that it is called on. Try calling a sleep on the thread you want to sleep rather than the main thread.
replace your current sleep call with
[self performSelector:#selector(sleepThread) onThread:thread withObject:nil waitUntilDone:YES];
then implement this method
-(void)sleepThread {
[NSThread sleepForTimeInterval:3.0];
}
The solution of ColdLogic is right, but it's neccesary put the flag waitUntilDone to YES, otherwise the method is never called.

Resources