2010年10月18日月曜日

「Cocoa Notification (NSNotification,NSNotificationCenter)」と「キー値監視」(3)

新しいスレッドを立ててそのスレッドから「通知」をそのまま送ると「スレッド・セーフでない」ので、セレクター使ってちゃんとメインスレッドのNSNotificationCenterから「通知」されるように書く必要あり。


前回からの続き。
前回のを実行したときのログが以下のように出力されたけど、気になる点が下から2行目。

ログの[470:5c03]は[プロセスID:スレッドID]として現れている。
わたしは、この下から2行目の処理がメインスレッドで実行されることを期待していたのだけれど、スレッドIDを見ると何故かしら新スレッドのIDで実行されているのがわかる。

2010-10-18 11:03:50.584 MyNotification[470:207] メインスレッド:処理開始
2010-10-18 11:03:50.589 MyNotification[470:5c03] 新スレッド:処理開始
2010-10-18 11:03:50.589 MyNotification[470:207] メインスレッド:処理終了
2010-10-18 11:03:51.593 MyNotification[470:5c03] 新スレッド:0
2010-10-18 11:03:52.596 MyNotification[470:5c03] 新スレッド:1
2010-10-18 11:03:53.599 MyNotification[470:5c03] 新スレッド:2
2010-10-18 11:03:54.602 MyNotification[470:5c03] 新スレッド:3
2010-10-18 11:03:55.605 MyNotification[470:5c03] 新スレッド:4
2010-10-18 11:03:55.608 MyNotification[470:5c03] 新スレッド:通知を送るよ。通知の名前はowataだよ。
2010-10-18 11:03:55.615 MyNotification[470:5c03] メインスレッド:通知owataを受け取ってowatayoメソッドを実行したよ。
2010-10-18 11:03:55.619 MyNotification[470:5c03] 新スレッド:処理終了

で、少し調べてみたところ、これは「スレッドセーフでない」状態ということらしい。
メインスレッド以外のスレッドから NSNotification で通知する場合 - 24/7 twenty-four seven

で、もう少し調べてみると、
セレクターを渡すことでメインスレッドのpostNotification:を実行させる方法があるようなので、そっちを試してみた。
前回書いた部分の以下のコードを変更する。
  1. /* 
  2.  * 新スレッド終了するときの通知させる処理 
  3.  */  
  4. - (void)didMyWork  
  5. {  
  6.  NSNotification *notification;  
  7.  notification = [NSNotification notificationWithName:@"owata" object:self userInfo:nil];  
  8.    
  9.  NSLog(@"新スレッド:通知を送るよ。通知の名前はowataだよ。");  
  10.  NSNotificationCenter *center;  
  11.  center = [NSNotificationCenter defaultCenter];  
  12.   
  13.  // これだと、  
  14.  // [center postNotification:notification];  
  15.  // 新スレッドで「通知」されるので、  
  16.  //   
  17.  // performSelectorOnMainThread:withObject:waitUntilDone:  
  18.  // こっちでメインスレッドから「通知」されるようにする   
  19.  //   
  20.  [center performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:NO];  
  21. }  


2010-10-18 11:06:50.287 MyNotification[531:207] メインスレッド:処理開始
2010-10-18 11:06:50.289 MyNotification[531:5c03] 新スレッド:処理開始
2010-10-18 11:06:50.290 MyNotification[531:207] メインスレッド:処理終了
2010-10-18 11:06:51.291 MyNotification[531:5c03] 新スレッド:0
2010-10-18 11:06:52.292 MyNotification[531:5c03] 新スレッド:1
2010-10-18 11:06:53.293 MyNotification[531:5c03] 新スレッド:2
2010-10-18 11:06:54.295 MyNotification[531:5c03] 新スレッド:3
2010-10-18 11:06:55.296 MyNotification[531:5c03] 新スレッド:4
2010-10-18 11:06:55.297 MyNotification[531:5c03] 新スレッド:通知を送るよ。通知の名前はowataだよ。
2010-10-18 11:06:55.299 MyNotification[531:207] メインスレッド:通知owataを受け取ってowatayoメソッドを実行したよ。
2010-10-18 11:06:55.300 MyNotification[531:5c03] 新スレッド:処理終了

これでオッケーな感じかな。


追記:何となく変な感じがするので次回、サンプルのコードを書き直す。

0 件のコメント:

コメントを投稿