线程NSProgressIndicator问题

时间:2009-09-08 11:24:08

标签: cocoa multithreading

我正在试图弄清楚如何使用辅助线程在UI中更新不确定的NSProgressIndicator,而主线程做了一些繁重的工作,就像几十个应用程序一样。这个片段基于Apple的“Trivial Threads”示例使用分布式对象(DO):

// In the main (client) thread...
- (void)doSomethingSlow:(id)sender
{ 
 [transferServer showProgress:self];

 int ctr;
 for (ctr=0; ctr <= 100; ctr++)
  {
  [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
  NSLog(@"running long task...");
  }
}

// In the secondary (server) thread...
- (oneway void)showProgress:(Controller*)controller
{
 [controller resetProgressBar];

 float ticks;
 for (ticks=0; ticks <= 100; ticks++)
  {
  [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
  [controller updateProgress:ticks];
  NSLog(@"updating progress in UI...");
  }
}

不幸的是,我无法让两个线程同时运行 。辅助线程将运行,主线程将一直等待,直到它完成或主线程运行,然后是辅助线程 - 但不能同时运行。

即使我将指针传递给服务器线程并要求它直接更新进度条(不调用主线程)也没有区别。似乎一旦主线程进入这样的循环,它就会忽略发送给它的所有对象。我仍然是Obj-C的新手,我真的很感激任何帮助。

2 个答案:

答案 0 :(得分:5)

AppKit根本不是线程安全的。你必须从主线程更新UI,否则会发生各种疯狂的事情(或者它不会起作用)。

最好的方法是在辅助线程上完成工作,在需要更新UI时回调主线程:

-(void)doSomethingSlow:(id)sender {

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

    // This will return immediately. 
}

-(void)threadedMethod {

    int ctr;
    for (ctr=0; ctr <= 100; ctr++) {
        NSLog(@"running long task...");

        [self performSelectorOnMainThread:@selector(updateUI)];
    }
}

-(void)updateUI {
    // This will be called on the main thread, and update the controls properly.
    [controller resetProgressBar];
}

答案 1 :(得分:2)

您可能想尝试切换线程。通常,UI更新和用户输入在主线程上处理,繁重的任务留给辅助线程。