gpt4 book ai didi

ios - 使用 NSRunLoop 正确使用辅助 NSThread

转载 作者:行者123 更新时间:2023-12-01 19:39:03 28 4
gpt4 key购买 nike

我有一个性能敏感的代码,实时处理视频播放帧。我在这里有一些可以并行化的工作,因为它是一个性能敏感的代码,延迟是我决定使用 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) _backgroundMethod代码:
- (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,我不应该在这里做任何计算。所以我正在参与 NSRunLoop使用无限计时器只是为了让它保持活力而无需持续运行 while环形。这是正确的方法吗?

2) 如果我可以在选择器中进行计算,我将通过 NSThread初始化阶段 - 我如何在不使用 performSelector 的情况下向 NSRunLoop 发出信号以执行一个循环?我想我不应该通过 performSelector 的完全相同的方法。因为那会是一团糟,对吧?

我已经阅读了 Apple 提供的大量信息,但所有这些几乎都是理论上的,而那些提供的代码示例让我更加困惑......

任何澄清将不胜感激。提前致谢!

编辑:

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

最佳答案

since it's a performance-sensitive code where latency is the key I decided to go with NSThread instead of GCD.



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

作为 Threading Programming Guide笔记:

Note: Although good for occasional communication between threads, you should not use the performSelector:onThread:withObject:waitUntilDone: method for time critical or frequent communication between threads.



如果您想要线程之间的低延迟通信,您通常需要使用信号量,例如 NSConditionLock而不是运行循环。

话虽如此,让我们来看看实际的问题。
performSelector:onThread:...接口(interface)一般用于一次性操作。实现长时间运行的专用线程的更常见方法是子类 NSThread并覆盖 main .像这样的东西(这是根据线程编程指南中的代码拼凑起来的,未经测试;多年来,我已经在 GCD 中完成了所有高性能工作,所以我可能在这里搞砸了一些东西)。
#import "WorkerThread.h"

#define NO_DATA 1
#define HAS_DATA 2

@implementation WorkerThread
static NSConditionLock *_condLock;
static NSMutableArray *_queue;

+ (void)initialize
{
if (self == [WorkerThread class]) {
_condLock = [[NSConditionLock alloc] initWithCondition:NO_DATA];
_queue = [NSMutableArray new];
}
}

- (void)main
{
// Until cancelled, wait for data, and then process it.
while (!self.cancelled)
{
[_condLock lockWhenCondition:HAS_DATA];
id data = [_queue firstObject];
[_queue removeObjectAtIndex:0];
[_condLock unlockWithCondition:(_queue.count == 0 ? NO_DATA : HAS_DATA)];

// Process data
}
}

// Submit work to the queue
+ (void)submitWork:(id)data {
[_condLock lock];
[_queue addObject:data];
[_condLock unlockWithCondition:HAS_DATA];
}

@end

您会产生一些线程,例如:
workers = @[[WorkerThread new], [WorkerThread new]];
for (worker in workers) {
[worker start];
}

[WorkerThread submitWork: data];

你会关闭这样的线程:
for (worker in workers) {
[worker cancel];
}

关于ios - 使用 NSRunLoop 正确使用辅助 NSThread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57921951/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com