0

次のようなコードの場合:

// Code in some object that will do work for an application:  

- (BOOL)shouldBeRunning  
{  
  [lockRunning lock];  
  BOOL shouldBeRunning= shouldRun;  
  [lockRunning unlock];  

  return shouldBeRunning;  
}  

- (void)stopRunning  
{  
  [lockRunning lock];  
  shouldRun= FALSE;  
  [lockRunning unlock];  
}  

- (void)threadEntryPoint:(id)object  
{  
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  

  NSRunLoop *runLoop = [NSRunLoop currentRunLoop];  

  // From an example I saw awhile back:  
  // A runloop with no sources returns immediately from runMode:beforeDate:  
  // That will wake up the loop and chew CPU. Add a dummy source to prevent it.  
  NSMachPort *dummyPort = [[NSMachPort alloc] init];  
  [runLoop addPort:dummyPort forMode:NSDefaultRunLoopMode];  
  [dummyPort release];  
  [pool release];  

  while ([self shouldBeRunning])   
  {  
    NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];  
    [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];  
    [loopPool drain];  
  }   
}  

- (BOOL)startRunning:(NSError **)errorPtr  
{  
  [self stopRunning];  // Stop if we are already running.  

  [runWorker release];  
  runWorker= [[NSThread alloc] initWithTarget:self selector:@selector(threadEntryPoint:) object:nil];  

  if(!runWorker)  
    return (FALSE);  

  // Start up the thread.  
  shouldRun= TRUE;  

  [runWorker start];  

  return TRUE;  
}  

- (void)doLotsOfStuff  
{  
  // Some operation that is long and intensive  
  // that should be done in the background.  
  // This function will call the app delegate, which will display the  
  // results. It will also notify the app on completion.  
}    

- (void)doStuff
{  
  // Commented out for illustrative purposes.  
  //[self startRunning];  // Fire thread up.  

  [self performSelector:@selector(doLotsOfStuff) onThread:runWorker withObject:nil waitUntilDone:NO];  
}    

// Out in the delegate:  
- (void)applicationDidFinishLaunching:(NSNotification*)aNotification  
{  
  // Do setup....  
  [workObject startRunning];  // Start the worker thread in the worker object.  
}  

- (void)buttonHandler:(id)sender  
{  
  [workObject doStuff];  
}  

そのため、アプリケーションにはボタンがあります。ユーザーがそれを押すと、タスクがワーカー スレッドで実行されます。タスクはアプリケーションにフィードバックを提供します。この場合、ボタンはタスクが完了するまで無効になります。そのコードをすべて表示したくないだけです。

書かれたコードでは、ボタンを 1 回押すと、遅延なくタスクが実行されます。多くの場合、もう一度ボタンを押しても同じ結果が得られます。ただし、2 回目のプレス (ほとんどの場合 3 回目以降) では、タスクの実行が大幅に遅れることがあります。デバッグ ステートメントを挿入すると、コードがスレッドで performSelector を実行し、その後遅延が発生し、最後にタスクが実行されることがわかります。

スレッドを再作成する doStuff の行のコメントを外すと (applicationDidFinishLaunching の行が冗長になります)、もちろん、毎回完全に機能します。

私が知る限り、スレッドは応答しない状態になっています。

何が起こっているのかについてのアイデアはありますか? セットアップと処理コードに明らかな問題はありますか? 任意の入力をいただければ幸いです。

4

0 に答える 0