How do I create a NSTimer on a background thread?

前端 未结 10 606
感情败类
感情败类 2020-11-28 02:04

I have a task that needs to be performed every 1 second. Currently I have an NSTimer firing repeatedly every 1 sec. How do I have the timer fire in a background thread (no

相关标签:
10条回答
  • 2020-11-28 02:49

    Swift only (although can probably be modified to use with Objective-C)

    Check out DispatchTimer from https://github.com/arkdan/ARKExtensions, which "Executes a closure on specified dispatch queue, with specified time intervals, for specified number of times (optionally). "

    let queue = DispatchQueue(label: "ArbitraryQueue")
    let timer = DispatchTimer(timeInterval: 1, queue: queue) { timer in
        // body to execute until cancelled by timer.cancel()
    }
    
    0 讨论(0)
  • 2020-11-28 02:50

    If you want to go pure GCD and use a dispatch source, Apple has some sample code for this in their Concurrency Programming Guide:

    dispatch_source_t CreateDispatchTimer(uint64_t interval, uint64_t leeway, dispatch_queue_t queue, dispatch_block_t block)
    {
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        if (timer)
        {
            dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
            dispatch_source_set_event_handler(timer, block);
            dispatch_resume(timer);
        }
        return timer;
    }
    

    Swift 3:

    func createDispatchTimer(interval: DispatchTimeInterval,
                             leeway: DispatchTimeInterval,
                             queue: DispatchQueue,
                             block: @escaping ()->()) -> DispatchSourceTimer {
        let timer = DispatchSource.makeTimerSource(flags: DispatchSource.TimerFlags(rawValue: 0),
                                                   queue: queue)
        timer.scheduleRepeating(deadline: DispatchTime.now(),
                                interval: interval,
                                leeway: leeway)
    
        // Use DispatchWorkItem for compatibility with iOS 9. Since iOS 10 you can use DispatchSourceHandler
        let workItem = DispatchWorkItem(block: block)
        timer.setEventHandler(handler: workItem)
        timer.resume()
        return timer
    }
    

    You could then set up your one-second timer event using code like the following:

    dispatch_source_t newTimer = CreateDispatchTimer(1ull * NSEC_PER_SEC, (1ull * NSEC_PER_SEC) / 10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // Repeating task
    });
    

    making sure to store and release your timer when done, of course. The above gives you a 1/10th second leeway on the firing of these events, which you could tighten up if you desired.

    0 讨论(0)
  • 2020-11-28 02:51

    This should work,

    It repeats a method every 1 second in a background queue without using NSTimers :)

    - (void)methodToRepeatEveryOneSecond
    {
        // Do your thing here
    
        // Call this method again using GCD 
        dispatch_queue_t q_background = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
        double delayInSeconds = 1.0;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
        dispatch_after(popTime, q_background, ^(void){
            [self methodToRepeatEveryOneSecond];
        });
    }
    

    If you are in the main queue and you want to call above method you could do this so it changes to a background queue before is run :)

    dispatch_queue_t q_background = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    dispatch_async(q_background, ^{
        [self methodToRepeatEveryOneSecond];
    });
    

    Hope it helps

    0 讨论(0)
  • 2020-11-28 02:52
    class BgLoop:Operation{
        func main(){
            while (!isCancelled) {
                sample();
                Thread.sleep(forTimeInterval: 1);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题