NSThread不加载选择器方法

时间:2012-05-17 10:35:03

标签: objective-c cocoa nsthread

在类的初始化方法中,我正在声明线程:

NSThread* myThread = [[[NSThread alloc] initWithTarget:self selector:@selector(m_run_thread) object:nil] autorelease];
[myThread start]; 

我也有一个布尔值,设置为NO。稍后在代码中我将布尔值设置为YES。

bool_run_progress_thread = YES;

方法m_run_thread的内容如下:

-(void) m_run_thread
{
    if (bool_run_progress_thread)
    {
         //do processing here
     }

bool_run_progress_thread = NO;
}

问题是永远不会访问方法m_run_thread。我做错了什么?

P.S。我还尝试使用以下(和更旧的)方法设置线程:

[NSThread detachNewThreadSelector:@selector(m_run_thread) 
                         toTarget:self 
                       withObject:nil];

......但也无济于事。

1 个答案:

答案 0 :(得分:2)

“......我只是让它显示一次”是的,这应该是它应该如何。在启动之后,一个线程从开始到结束运行一次(暂时忽略这里的错误),并且到达结束时,线程基本上已经死了并且消失了。

如果您希望线程重复执行,您必须自己做好准备:

- (void) m_run_thread
{
    for (;;) 
    {
        if (bool_run_progress_thread)
        {
            //do processing here
            bool_run_progress_thread = NO;
        }
    }
}

但是这段代码还有很多问题:基本上,在运行时,代码会形成一个繁忙的等待循环。假设bool_run_progress_thread只在短时间内成为现实,后台线程应该在大多数时间都处于休眠状态。 Insead,如果你尝试代码作为它的代表,它将消耗CPU时间(和大量的)。

更好的方法是condition variables

@class Whatsoever 
{
    NSCondition* cvar;
    BOOL doProgress;
    ...
}
...
@end

- (void) m_run_thread
{
    for (;;) 
    {
        [cvar lock];

        while (!doProgress) 
        {
            [cvar wait];
        }

        doProgress = NO;
        [cvar unlock];

        ... do work here ...
    }
}

并且为了触发执行,你可以:

- (void) startProgress 
{
    [cvar lock];
    doProgress = YES;
    [cvar signal];
    [cvar unlock];    
}

以这种方式做事还会解决另一个微妙的问题:对全局标记(您的bool_run_progress_thread,我的doProgess)所做更改的可见性。根据处理器及其内存顺序的不同,在没有特殊保护的情况下进行的更改可能会或可能不会对其他线程可见。这个问题也由NSCondition处理。