How to Stop a Dispatchqueue in Swift

how to stop a dispatchQueue in swift

I'm not sure if there are best practices here, but I would consider doing what you are doing with a Timer rather than the DispatchQueue.

class GifClass: UIViewController {

@IBOutlet weak var gifImage: UIImageView!
@IBOutlet weak var skipButton: UIButton!

var timer = Timer()

override func viewDidLoad() {
super.viewDidLoad()

gifImage.loadGif(name: "promed")

timer = Timer.scheduledTimer(timeInterval: 11, target: self, selector: #selector(timerAction), userInfo: nil, repeats: false)
}

@objc func timerAction() {
performSegue(withIdentifier: "introLogin", sender: self)
}

@IBAction func skip(_ sender: Any) {
timer.invalidate()
performSegue(withIdentifier: "introLogin", sender: self)
}
}

Swift Cancel DispatchQueue Process

There is no way to stop or "kill" a DispatchWorkItem or NSOperation from outside. There is a cancel() method, but that merely sets the isCancelled property of the item or operation to true. This does not stop the execution of the item itself. Ans since recv is blocking, there is no way to check the isCancelled flag during execution. This means the answer posted by Vadian unfortunately wouldn't do anything.

According to the Apple docs on NSOperation.cancel:

This method does not force your operation code to stop.

The same goes for NSOperationQueue.cancelAllOperations:

Canceling the operations does not automatically remove them from the queue or stop those that are currently executing.

You might think it is possible to drop down to using a raw NSThread. However, the same principle applies hier. You cannot deterministically kill a thread from the outside.

Possible solution: timeout

The best solution I can think of is to use the timeout feature of the socket. I don't know where UDPServer comes from, but perhaps it has a built in timeout.

Possible solution: Poor man's timeout (send packet to localhost)

Another option you can try is to send some UDP packets to yourself after a certain time has elapsed. This way, recv will receive some data, and execution will continue. This could possibly be used as a "poor man's timeout".

Stop a DispatchQueue that is running on the main thread

You can use DispatchWorkItems. They can be scheduled on DispatchQueues and cancelled before their execution.

let work = DispatchWorkItem(block: {
self.isShootingOnHold = false
self.shoot()
self.shootingEngine = Timer.scheduledTimer(timeInterval: (Double(60)/Double(self.ratePerMinute)), target: self, selector: #selector(ShootingEnemy.shoot), userInfo: nil, repeats: true)
})
DispatchQueue.main.asyncAfter(deadline: .now() + (delay * Double(isDelayAccounted.hashValue)) + extraDelay, execute: work)
work.cancel()

How to quit DispatchQueue.main.asyncAfter in Swift

In Swift we have something called ARC(Automatic Reference Counting).
ARC will make sure any object with at least one strong reference to it, will not be removed from memory.

In your case you're creating a strong reference to self in the closure of the async task created by DispatchQueue.main.asyncAfter.

You need to tell the compiler that this reference is either weak or unowned(See attached link for more info.), this will enable the instance of self to be deinitialised even though you have a reference to self from the closure.

The weak keyword can be used in cases where you want the closure to run and make actions that doesn't require a reference to self. This is helpful to use if you don't know if self is alive or not.

The unowned keyword can be used in cases where you don't need the closure to run without a reference to self. This must be used in cases where you know self self is still alive.

Getting a weak or unowned reference of self in the closure can be achieved like in the example below:

DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
[weak self] in
self?.doSomething()
}

DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
[unowned self] in
self.doSomething()
}

It's worth mentioning that if you're not using a deadline, but calling .async { ... } directly does not result in capturing self and therefore can be used safely without defining weak/unowned self.

Unable to stop DispatchQueue.global().async task on swift

Issue has been resolved, actually should't have used dispatch global async in first place. Tried doing it with a timer and it worked, vibrating after each secs and it doesn't freeze the UI, also gets stopped easily after just calling timer.invalidate(). Thanks for the help guys :)

Is there a way to cancel a DispatchQueue concurrentPerform operation?

DispatchQueue.concurrentPerform causes the block to be executed the specified number of times, and waits for all iterations to complete. There is no way to prevent that. (The blocks run in parallel if the target queue is a concurrent queue.)

Of course each work item can “early return” if some condition is met, but that won't affect the other work items.

Your code crashes because leave() is called on the dispatch group more times than enter().



Related Topics



Leave a reply



Submit