- - PR -
BackgroundWorkerでTimerをStop, Startさせた場合の動作
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-03-27 13:21
VS2005 C# Windowsフォームのアプリケーションです。
フォームが開いている間、一定間隔で行う処理があるため、 Timer(System.Windows.Forms.Timer)を用いて処理を行っています。 また、フォーム上でのある操作をトリガとして起動される別のタスクがありますが、 実行中もUIを応答させたいので、このタスクをバックグラウンドで実行するために、 BackgroundWorker を使用しています。 ここで、BackgroundWorkerで実行されるタスクを実行中は タイマーの処理を止めたいので、DoWorkのイベントハンドラ内で タイマーをStopして、処理を行った後Startさせています。 再現コードを以下に示しますが、これを実行すると、 フォーム起動したときは1秒間隔で「Tick」が出力されるのですが、 ボタンを押して BackgroundWorker のタスクを実行すると、 タスクの終了後、「Tick」が全く出力されなくなります。 タイマーの Enabled は true になっているにも関わらずです。 解決策は見つかっていて、 timer1.Stop をRunWorkerAsync の呼び出し前に、 timer1.Start を RunWorkerCompleted のハンドラ内に書けば正常に動作しました。 ただ、なぜこのコードで動作しないのかが納得できないので、 原因のわかる方がいましたら教えてください。 よろしくお願いします。
[ メッセージ編集済み 編集者: KI 編集日時 2007-03-27 15:29 ] | ||||||||
|
投稿日時: 2007-03-27 13:39
RunWorkerCompleted で、e.Error の値をチェックしてみては?
| ||||||||
|
投稿日時: 2007-03-27 14:06
お返事ありがとうございます。
デバッガで確認してみましたが、e.Error は null でした。 | ||||||||
|
投稿日時: 2007-03-27 14:49
コントロールはUIのスレッドから操作しなければならないという制約ですね。
| ||||||||
|
投稿日時: 2007-03-27 15:19
あれ?予想と違う結果が。。。 System.Windows.Timer なんてものは無い筈なので、System.Windows.Forms.Tiemr を使っているんですよね? こいつはコントロールではなく Component なので、「コントロールは、その実体を生成したスレッド以外から操作してはならない」という制約には引っかからないような気もするんですが。。。 念のため DoWork() 内から操作する時は Form.Invoke() してみるとか。 | ||||||||
|
投稿日時: 2007-03-27 15:30
なちゃさん、渋木さん。お返事ありがとうございます。
私も「コントロールはUIのスレッドから操作しなければならない」ことは把握していました。 そもそも .NET 2.0 ではこれをやるとInvalidOperationException が発生します。 ですが、Timer は Component なので大丈夫だと思っていましたし、 例外もスローされませんでしたので、これが原因とは考えませんでした。 試しにInvokeを使って以下のように書き直したところ正常に動作しました。
いずれにせよ Timer オブジェクトが、Enabled が true のまま Tick イベントを発生させないような状態になるくらいなら、 不正な操作が行われた時点で InvalidOperationException をスローすべきと思うのですが…
ご指摘のとおり、System.Windows.Forms.Tiemr の誤りでした。元記事修正しておきました。 | ||||||||
|
投稿日時: 2007-03-27 15:46
MSDN ライブラリより引用。
というわけで、エラーが出ないかつイベントが発生しないのが正常動作ですので(そのスレッドで Application.Run してあげれば発生しますよたぶん)。 とりあえず調べようよという話はおいておいて、実装の話で考えてみると、どうせWM_TIMERを使用していると思われるので、どのスレッドでも初期化可能で、かつそのスレッドにおいてメッセージループが開始されていないと発生しない(開始されてから発生する)というのはまぁ妥当な実装かと。 | ||||||||
|
投稿日時: 2007-03-27 16:53
yaさん、ありがとうございます。
最初にMSDN読むべきでしたね…スッキリしました。 System.Windows.Forms.Timer はメッセージポンプがないと動作しないのですね。 それならば、この実装も納得できます。 |
1