NSTimerの使い方メモ

昨日の画面真っ黒状態が解決できなく,デバッガも使えないが,メッセージループは生きている.それならばウィンドウからたどれる全てのViewの情報を一定時間周期でダンプしてやればいいかなと考えた.

そのときのタイマーの使い方メモ.

static int cnt =0;

//3秒ごとにカウントアップして表示
var timer = NSTimer.CreateRepeatingTimer(new TimeSpan(0, 0, 3), delegate { Debug.WriteLine("Timer {0}.", cnt++); });
NSRunLoop.Current.AddTimer(timer, "NSDefaultRunLoopMode");                 

System.TimerがないのでNSTimerを使った.実行周期やdelegateを渡してNSTimerのインスタンスを作りそれを実行ループに登録すればよい.
NSRunLoopに登録するときのモード名がクラスに定義されていなくて,何を指定すればよいかが分からずに困ったけど,ライブラリで定義されているそのままな名前を文字列で指定すればよいみたい.

NSTimer とSystem.Timers.Timerの違いは、どのスレッドで実行されるかと、時間精度の違いのようです。NSTimerはUIのイベントループと同じスレッドで実行されて、時間精度はサブミリ秒(100usec単位)であるそうです。UIイベントと同じスレッドで動くので、例えばUIのラベルテキスト変更などを実行しても問題は生じません。System.Timers.Timerは、ThreadPoolで実行され、時間精度は+-10~20msecといった(実行したところ)感じです。UIと別スレッドで動くため、ラベルテキスト変更などUIにアクセスするときは、delegateをInvokeOnMainThread()に渡して、Mainスレッドで実行させます。

このあたりの振る舞いは、NSTimerがWPFのDispatchと同じ仕組み、System.Timers.TimerはWinFormでよくある別スレッドからのUIアクセスでInvoke()を使えと言われるのと同じ仕組み、となります。