【问题标题】:NSThread sleepfortimeinterval blocks main threadNSThread sleepfortimeinterval 阻塞主线程
【发布时间】:2016-12-13 17:29:36
【问题描述】:

我想模拟与服务器的通信。由于远程服务器会有一些延迟,我想使用它上面的后台线程

 [NSThread sleepForTimeInterval:timeoutTillAnswer];

线程是使用 NSThread 子类创建并启动的……但是我注意到 sleepForTimeInterval 阻塞了主线程……为什么??? NSThread 默认不是 backgroundThread 吗?

线程是这样创建的:

   self.botThread = [[PSBotThread alloc] init];
    [self.botThread start];

更多信息: 这是机器人线程子类

- (void)main
{
    @autoreleasepool {
        self.gManager = [[PSGameManager alloc] init];
        self.comManager = [[PSComManager alloc] init];
        self.bot = [[PSBotPlayer alloc] initWithName:@"Botus" andXP:[NSNumber numberWithInteger:1500]];
        self.gManager.localPlayer = self.bot;
        self.gManager.comDelegate = self.comManager;
        self.gManager.tillTheEndGame = NO;
        self.gManager.localDelegate = self.bot;
        self.comManager.gameManDelegate = self.gManager;
        self.comManager.isBackgroundThread = YES;
        self.comManager.logginEnabled = NO;
        self.gManager.logginEnabled = NO;
        self.bot.gameDelegate = self.gManager;
        BOOL isAlive = YES;
        // set up a run loop
        NSRunLoop *runloop = [NSRunLoop currentRunLoop];
        [runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        [self.gManager beginGameSP];
        while (isAlive) { // 'isAlive' is a variable that is used to control the thread existence...
            [runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }



    }
}

- (void)messageForBot:(NSData *)msg
{
    [self.comManager didReceiveMessage:msg];
}

我想从主线程调用“messageForBot”...后台线程也应该调用主线程上的一个方法进行通信..gManager 对象内部的时间间隔睡眠......

【问题讨论】:

  • 显示你是如何创建线程的,它做了什么以及何时调用sleepForTimeInterval:(它会在调用它时延迟当前线程)。
  • 这就是我创建线程的方式... [self.botThread start]; ...调用 NSThread 子类 PSBotThread main 方法 .. .
  • 但是它有什么作用呢? sleepForTimeInterval 在哪里?
  • 线程使用一个对象来接收消息并返回一个结果...... sleepForTimeInterval 在这个对象内

标签: ios nsthread


【解决方案1】:

它会阻塞任何正在运行的线程 sleepForTimeInterval。在另一个线程上运行它来模拟你的服务器延迟,如下所示:

dispatch_queue_t serverDelaySimulationThread = dispatch_queue_create("com.xxx.serverDelay", nil);
dispatch_async(serverDelaySimulationThread, ^{
     [NSThread sleepForTimeInterval:10.0];
     dispatch_async(dispatch_get_main_queue(), ^{
            //Your server communication code here
    }); 
});

【讨论】:

  • 我认为这行不通......也许线程创建应该在 dispatch_async 中?
  • 我正在使用它,它工作正常。我做了同样的事情来模拟网络延迟。 dispatch_queue_create 已经创建了另一个线程。 dispatch_async 中的 sleepForTimeInterval 会导致该线程休眠。
  • 对我来说它阻塞了主线程...如果可以的话,请帮我解决这个问题stackoverflow.com/questions/32910632/…
【解决方案2】:

尝试在你的线程类中创建一个名为 sleepThread 的方法

-(void)sleepThread
{
   [NSThread sleepForTimeInterval:timeoutTillAnswer];
}

然后让它从你的主线程休眠

[self.botThread performSelector:@selector(sleepThread) onThread:self.botThread withObject:nil waitUntilDone:NO];

将更新从您的机器人线程发送到您的主线程。

dispatch_async(dispatch_get_main_queue(), ^{
    [MainClass somethinghasUpdated];
});

旁注

要创建 RunLoop,我认为您需要做的就是

// Run the Current RunLoop
[[NSRunLoop currentRunLoop] run];

【讨论】:

  • 我不需要让它从主线程休眠...它应该在收到主线程的消息后让它自己休眠
  • 好的,所以你希望它在方法中休眠 - (void)messageForBot:(NSData *)msg ?
  • 不,该方法将在主方法中创建的一个内部对象上调用另一个方法...我需要它休眠...而不像现在这样阻塞 UI
  • 好的,所以您的主线程将调用 messageForBot:该方法将调用您的 comManager,然后调用睡眠。要从主线程调用 messageBot,请执行此操作 [self.botThread performSelector:@selector(messageForBot:) onThread:self.botThread withObject:someDataObject waitUntilDone:NO];
【解决方案3】:

斯威夫特:

let nonBlockingQueue: dispatch_queue_t = dispatch_queue_create("nonBlockingQueue", DISPATCH_QUEUE_CONCURRENT)
dispatch_async(nonBlockingQueue) {
    NSThread.sleepForTimeInterval(1.0)
    dispatch_async(dispatch_get_main_queue(), {
        // do your stuff here
    })
}

【讨论】:

    猜你喜欢
    • 2018-02-16
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多