- ベストアンサー
.NET非同期イベント処理法について
VS2010 Express VC++にてWindows Applicationを作成しております。 Form1のイベント(今回の場合はドラッグ&ドロップ)でスタートし、実行中の処理に対して、別のイベント(ボタンクリック等)によって処理内容を中途変更したいのですが、方法が分かりません。 具体的方法をご教示いただくか、又は参照先をお教えいただけないでしょうか。 宜しお願い致します。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
まず,処理方法から。 ・イベントの処理をバックグラウンドのスレッドで行うようにする →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
その他の回答 (1)
- wormhole
- ベストアンサー率28% (1626/5665)
>例えば、メインのルーチンを実行中に、フォーム上のボタンを押せるようにするにはどうするか等・・・。 その「メインのルーチン」というのをバックグラウンドで動かせばいいです。
お礼
有難うございます。 バックグラウンドで動かすためにNo1さんのご回答にあったBackgroundWorkerコンポーネントを使うわけですね。トライしてみます。
補足
質問者です。 ご回答をヒントに所望のプログラムを作成することができました。 有難うございました。
お礼
早速のご回答有難うございます。 概略の考え方は分かりました。 ただ、VC++のウインドウズアプリケーションで作成する場合の具体的方法が分かりません。 例えば、メインのルーチンを実行中に、フォーム上のボタンを押せるようにするにはどうするか等・・・。 ご教示頂けるようでしたら、宜しくお願い致します。
補足
質問者です。 ご回答をヒントにBackgroundWorkerを用いて、所望のVC++プログラムを作ることができました。 誠に有難うございました。