掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
スレッド間のエラーを解消するには (ID:148133)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
> BackgroundWorkerを使用したのですが、Label1には何も表示されません。 使い方が間違っています。 BackgroundWorker を使うなら、RunWorkerAsync メソッドから 実行されるための「DoWork イベント」の記述が必要です。 今回のコードでは、Form1 に DoWork イベントの処理が記載されて いないため、ワーカースレッドは「何もせずに即座に終了」しています。 この場合、「BackgroundWorker のワーカースレッド」と 「UI スレッド」と「TimerCallback のスレッド」が それぞれ別物であることに注意してください。 スレッド管理を BackgroundWorker に任せたのであれば、 本来は TimerCallback の出番はありません。 今回のサンプルであれば、DoWork イベントの中で 「1000ミリ秒 Sleep させてから、ReportProgress を呼ぶ」ことで、 処理できるでしょう。それがやりたいことに合致しているかは別として。 > BackgroundWorker1_ProgressChangedは別スレッド扱いなのでしょうか。 BackgroundWorker クラスの ProgressChanged イベントは、 「RunWorkerAsync メソッドを呼び出したスレッド」 にて呼び出されます。今回の場合は Form1 の UI スレッドですね。 > Public Sub MyClock(o As Object) > Form1.BackgroundWorker1.WorkerReportsProgress = True > Form1.BackgroundWorker1.ReportProgress(CInt(DateTime.Now.Second)) > End Sub 上記のようなことは、絶対に行ってはいけません。 マルチスレッドプログラミングにおいては、操作できるのは基本的に、 自身のスレッド上で動いているオブジェクトのみに限定されます。 不用意に他のスレッドのオブジェクトの状態を変化させてしまうと、 同時実行制御の上で問題を生じ、再現させにくいトラブルを 生じさせてしまう要因となります。 どうしても他のスレッドに進捗情報を伝える必要がある場合には、 以下のようにして対処することができます。 (案1) 相手側のスレッドに対して情報を通知し、実際の処理は 相手のスレッドに処理を「依頼」する形をとる。 → BackgroundWorker はこの方法をとるために、内部で AsyncOperationManager / AsyncOperation クラスを利用しています。 BackgroundWorker を用いず、自身で管理しているスレッドから UI スレッドを操作したいような場合には、前回紹介した URL に 記載されている方法を使うのが良いでしょう。 (案2) フィールド変数やプロパティのアクセスなどは避け、 常に「スレッドセーフな呼び出しが保証されたメソッド」のみを使う。 → スレッドセーフなコードであれば、複数のスレッドから 同時並行的に実行されても、特に問題は生じません。 (案3) いずれかのスレッドが状態を変更させている間は、 他のスレッドがその変数やプロパティを読み書きしないように 何かしらの同時実行制御や排他制御を施す。 → ReaderWriterLock や Interlocked などのクラスを通じて 変数を操作するようにするとか、あるいは SyncLock で囲むとか。 # 具体的な手順は、前回紹介した URL をご覧ください。
←解決時は質問者本人がここをチェックしてください。
更新する
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.