Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/103.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在nsrunlop中正确使用辅助NSThread_Ios_Objective C_Multithreading_Nsthread_Nsrunloop - Fatal编程技术网

Ios 在nsrunlop中正确使用辅助NSThread

Ios 在nsrunlop中正确使用辅助NSThread,ios,objective-c,multithreading,nsthread,nsrunloop,Ios,Objective C,Multithreading,Nsthread,Nsrunloop,我有一个性能敏感的代码,用于实时播放视频帧。我在这里做了一些可以并行化的工作,因为这是一个性能敏感的代码,延迟是关键,所以我决定使用NSThread而不是GCD 我需要的:我需要有NSThread,它将在特定时间段安排一些工作。线程完成其工作后,将进入睡眠状态,直到新的工作到达 不幸的是,关于NSThread在互联网上的正确使用技术,没有太多的信息,所以我根据我设法找到的信息位组装了我的例程 您可以在上面找到整个工作流: 1) 初始化我的NSThread。此代码只按预期启动一次 _myThrea

我有一个性能敏感的代码,用于实时播放视频帧。我在这里做了一些可以并行化的工作,因为这是一个性能敏感的代码,延迟是关键,所以我决定使用
NSThread
而不是
GCD

我需要的:我需要有
NSThread
,它将在特定时间段安排一些工作。线程完成其工作后,将进入睡眠状态,直到新的工作到达

不幸的是,关于
NSThread
在互联网上的正确使用技术,没有太多的信息,所以我根据我设法找到的信息位组装了我的例程

您可以在上面找到整个工作流:

1) 初始化我的
NSThread
。此代码只按预期启动一次

_myThread = [[NSThread alloc] initWithTarget:self selector:@selector(_backgroundMethod) object:nil];
 _myThread.threadPriority = 0.8;    //max priority is 1.0. Let's try at 0.8 and see how it performs
[_myThread start];
2)
\u背景方法
代码:

- (void)_backgroundMethod
{
    NSLog(@"Starting the thread...");
    [NSTimer scheduledTimerWithTimeInterval:FLT_MAX target:self selector:@selector(doNothing:) userInfo:nil repeats:YES];

    BOOL done = false;
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    do {
        [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    } while (!done);
}

- (void)doNothing:(NSTimer *)sender { }
3) 当线程有东西要处理时,我会打下一个电话:

[self performSelector:@selector(_doSomeCalculation) onThread:_myThread withObject:nil waitUntilDone:NO];
哪个调用下一个方法:

- (void) _doSomeCalculation
{
    //do some work here
}
所以我的问题是:

1) 当我初始化NSThread时,我传递一个选择器。那个选择器的用途是什么?据我所知,这个选择器的唯一用途是控制线程的RunLoop,我不应该在这里进行任何计算。因此,我正在使用一个无限计时器启动
nsrunlop
,以使其保持活动状态,而不必在
循环期间不断运行
。这是正确的方法吗

2) 如果我可以在我在
NSThread
init阶段传递的选择器中进行计算,那么我如何在不使用
performSelector
的情况下向nsrunlop发送信号以执行一个循环呢?我想我不应该通过与
performSelector
完全相同的方法,因为它会很混乱,对吗

我已经阅读了苹果提供的很多信息,但所有这些几乎都是理论性的,而那些提供的代码示例更让我困惑

如有任何澄清,将不胜感激。提前谢谢

编辑:

还有一个问题-如何计算线程所需的
stackSize
?有什么技巧可以做到这一点吗

因为这是一个性能敏感的代码,延迟是关键,所以我决定使用NSThread而不是GCD

你通常不应该这样做,除非你有一个坚实的理解GCD和确切地知道你要放弃什么。正确使用,GCD是高度优化的,并与操作系统紧密集成。手动使用NSThread,然后使用
performSelector
在ObjC中运行循环,这尤其令人惊讶。以这种方式调用PerformSelect会引入与GCD串行队列相同的未知延迟。如果线程已经很忙,那么您将对选择器进行排队,就像对块进行排队一样(但您将增加
objc\u msgSend
的开销)。GCD并发队列的性能会更好。为了匹配GCD,您需要实现一个适当的线程池(或者至少添加取消)。做得好,对于特定的用例,这可能比GCD更好,但它必须做得很好,这很复杂

如注释所示:

注意:虽然对于线程之间的偶尔通信很好,但对于线程之间的时间关键型或频繁通信,不应使用performSelector:onThread:withObject:waitUntilDone:方法

如果希望线程之间的通信延迟较低,通常需要使用信号量,例如
NSConditionLock
,而不是runloop

也就是说,让我们进入实际问题

performSelector:onThread:…
接口通常用于一次性操作。实现长时间运行的专用线程的更常见方法是子类化
NSThread
并重写
main
。类似这样的东西(这是根据《线程编程指南》中的代码组合而成的,未经测试;我已经在GCD中完成了多年的高性能工作,所以我可能在这里搞错了一些东西)

您将生成一些线程,如:

workers = @[[WorkerThread new], [WorkerThread new]];
for (worker in workers) {
    [worker start];
}

[WorkerThread submitWork: data];
for (worker in workers) {
    [worker cancel];
}
然后关闭线程,如:

workers = @[[WorkerThread new], [WorkerThread new]];
for (worker in workers) {
    [worker start];
}

[WorkerThread submitWork: data];
for (worker in workers) {
    [worker cancel];
}

糟糕的决定。使用
GCD
。它被设计为“杀死”
NSThread
。你需要的东西都有了。你现在只是在重新发明GCD。您可以使用direct
GCD
或Objective-C的it包装器
NSOperationQueue
Hello!以下是Apple在《从线程迁移》一文中对
NSThread
的看法-
重要的是要记住,队列不是替换线程的灵丹妙药。队列提供的异步编程模型适用于延迟不是问题的情况。尽管队列提供了配置队列中任务的执行优先级的方法,但较高的执行优先级并不能保证在特定时间执行任务。因此,在需要最小延迟的情况下,线程仍然是更合适的选择,例如在音频和视频播放中。
所以我想指出,我决定尝试
NSThread
,因为在特定情况下,
GCD
存在某些问题,比如延迟随着时间的推移而减少,以及不同设备上的性能不均衡。我需要更多地控制我的任务是如何执行的,并学习如何正确地执行它。我认为苹果在这里的意思是,你在线程中执行简单的顺序工作:从输入中获取数据,处理它,将它放入输出。当您创建运行循环并执行选择器时,没有这种调度机制。执行选择器也比直接函数调用花费更多的时间,如果延迟如此重要,你应该考虑一下。在这一点上,我将不得不使用@Cy-4AH。可以使用GCD在单个队列上完成所有工作,也可以对每个进程使用
NSThread
而不使用run循环。看来你不止一个。在这两种情况下,当需要在此线程中执行的工作太多而无法处理时,都会产生延迟。打开的线程数量将增加,或者先前的t