まず,処理方法から。
・イベントの処理をバックグラウンドのスレッドで行うようにする
→Taskクラス,BackgroundWorkerクラス
・処理内容の変更を要求する方法を用意する
→AutoResetEvent, ManualResetEventなどの同期オブジェクト,Booleanフィールド等
・イベント処理コードは,定期的に処理内容の変更要求を確認し,変更要求が出ていればそれに従う
という手順を踏みます。
UIスレッドで何らかの処理を行っている最中に,別のUIイベントは発生しません。
このため,UIスレッドでの処理は短くし,長時間かかる処理は別のスレッドで行うようにします。
簡易な方法はBackgroundWorkerクラスをを使う方法ですが,BackgroundWorker自体がコンポーネントであるため,
色々なイベントで別のスレッドを使って処理を行うには向いていません。
複数のイベントで長時間処理を行うような場合は,Taskクラスを使って処理を行います。
さて,別のスレッド (ワーカースレッド) に要求を伝える場合 (典型例はキャンセル),
UIスレッドから直接ワーカースレッドの処理に介入することはできません。
なので,ワーカースレッドにはフィールドや同期用オブジェクトを使って,UIスレッドから処理をお願いすることになります。
もちろん,お願いをフィールドに設定しただけではだめで,ワーカースレッドがそれを見にいく必要があります。
これは,意図的に見にいくように処理を作ることになります。
処理を依頼するようなサンプルプログラムを簡単に組んでみました。
Console Applicationで動作します (VS2013/.NET 4.5.1で確認しているため,VS2010では未サポートのものがあるかもしれません)
インデントの為に_を使っています。_をスペースに置換して使ってください。
Enterを押すたびに表示される値が2倍になり,Ctrl + Zで終了します。
Imports System.Threading
Module Module1
____Private doubleRequest As Boolean
____Private source As New CancellationTokenSource()
____Sub Main()
________doubleRequest = False
________Dim t As New Task(AddressOf WorkerTask, source.Token)
________t.Start()
________Do
____________Dim s As String = Console.ReadLine()
____________If s Is Nothing Then
________________source.Cancel()
________________Exit Do
____________End If
_____________doubleRequest = True
________Loop
________t.Wait()
________Console.WriteLine()
________Console.WriteLine("Finished.")
________Console.ReadLine()
____End Sub
____Sub WorkerTask()
________Dim number As Integer = 1
________While Not source.Token.IsCancellationRequested
____________If doubleRequest Then
________________doubleRequest = False
________________Console.WriteLine("Doubled Requested ({0} to {1})", number, number * 2)
________________number *= 2
____________End If
____________Console.WriteLine(number)
____________number += 1
____________Thread.Sleep(TimeSpan.FromSeconds(1))
________End While
____End Sub
End Module
お礼
早速のご回答有難うございます。 概略の考え方は分かりました。 ただ、VC++のウインドウズアプリケーションで作成する場合の具体的方法が分かりません。 例えば、メインのルーチンを実行中に、フォーム上のボタンを押せるようにするにはどうするか等・・・。 ご教示頂けるようでしたら、宜しくお願い致します。
補足
質問者です。 ご回答をヒントにBackgroundWorkerを用いて、所望のVC++プログラムを作ることができました。 誠に有難うございました。