|
2018/11/15(Thu) 16:33:48 編集(投稿者)
■No89268 (コリオリ さん) に返信 > 今後、BackgroundWorkerを使用した非同期処理を考えていて(勉強中)、
BackgroundWorker を使う場合の方針として:
(1) DoWork 内では、ローカル変数のみを使う。コントロールの読み書きは御法度。
(2) DoWork 内で、Form のフィールド変数などにアクセスするのは避ける。 BeginInvoke / Invoke などでのコントロール操作も極力避ける。
(3) 進捗表示が必要なら、ReportProgress メソッドと ProgressChanged イベントを使う。
(4) BackgroundWorker が稼働中に、呼び出し元フォームが終了することの是非も検討しておく。
> ここで一つ疑問に思ったのが、Application.Idleは別スレッドの動作も含めて > アイドル状態となった時に発生するのでしょうか?
Idle を呼び出すのは UI スレッドの役目であり、他のスレッドは直接影響しません。 現在の UI スレッドのメッセージキューが空になった時にのみ発生します。 「空の時」ではなく、「空になった時」である点が肝。
新しい Windows メッセージが来ていない場合には、現在アイドル状態で あったとしても、Idle イベントは発生しないのでご注意を。
--- 以下蛇足 ---
メッセージループを回す個所は幾つかありますが、その一つがモーダル ダイアログ。 たとえば ShowDialog メソッドを呼び出した場合、最終的には、 Const msoloopModalForm As Intger = 4 Application.ThreadContext.FromCurrent().RunMessageLoop(msoloopModalForm, コンテキスト) というコードに行きつき、ここでメッセージループが回されることになります。
VB のスタートアップ フォームはモーダルではありませんが、これもメッセージループが処理されています。
スタートアップフォームは基本的に、System.Windows.Forms.Application.Run メソッドから呼ばれます。 もう少し具体的に言えば、 System.Windows.Forms.Application.Run( ApplicationContext ) もしくは System.Windows.Forms.Application.Run( Form ) のいずれかから呼び出されるということです。 (C# プロジェクトだと、Program.cs 内の static void Main() に上記の記述があります)
そしてこの Application.Run メソッドが Const msoloopMain As Intger = -1 Application.ThreadContext.FromCurrent().RunMessageLoop(msoloopMain, コンテキスト) のようにして、メッセージ ループを回しています。
VB だと、既定でアプリケーション フレームワークが有効になっているため、 Application.Run という記述は見えないのですが、コンパイル時に自動的に Public Sub Main(commandLine As String()) Application.SetCompatibleTextRenderingDefault(bool) My.Application.Run(commandLine) End Sub に相当する処理が実装されます。
そして上記の、My.Application.Run メソッドからは、先述の System.Windows.Forms.Application.Run( ApplicationContext ) が呼び出されているという流れです。
ちなみに、このアプリケーション フレームワークからの処理の流れは、 Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load Me.TopMost = True Me.Close() End Sub End Class というコードを書いてデバッグ実行すると見えてきます。
上記をデバッグ実行すると、ObjectDisposedException 例外で停止してしまうのですが、 その時のスタック トレースに、My.Application.Run(commandLine) からの流れが記載されています。
場所 System.Windows.Forms.Control.CreateHandle() 場所 System.Windows.Forms.Form.CreateHandle() 場所 System.Windows.Forms.Control.get_Handle() 場所 System.Windows.Forms.ContainerControl.FocusActiveControlInternal() 場所 System.Windows.Forms.Form.SetVisibleCore(Boolean value) 場所 System.Windows.Forms.Control.set_Visible(Boolean value) 場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun() 場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel() 場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine) 場所 WindowsApp1.My.MyApplication.Main(String[] Args) ()
|