• ベストアンサー

.NET非同期イベント処理法について

VS2010 Express VC++にてWindows Applicationを作成しております。 Form1のイベント(今回の場合はドラッグ&ドロップ)でスタートし、実行中の処理に対して、別のイベント(ボタンクリック等)によって処理内容を中途変更したいのですが、方法が分かりません。 具体的方法をご教示いただくか、又は参照先をお教えいただけないでしょうか。 宜しお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

まず,処理方法から。 ・イベントの処理をバックグラウンドのスレッドで行うようにする →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

goo-learner
質問者

お礼

早速のご回答有難うございます。 概略の考え方は分かりました。 ただ、VC++のウインドウズアプリケーションで作成する場合の具体的方法が分かりません。 例えば、メインのルーチンを実行中に、フォーム上のボタンを押せるようにするにはどうするか等・・・。 ご教示頂けるようでしたら、宜しくお願い致します。

goo-learner
質問者

補足

質問者です。 ご回答をヒントにBackgroundWorkerを用いて、所望のVC++プログラムを作ることができました。 誠に有難うございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

  • wormhole
  • ベストアンサー率28% (1622/5659)
回答No.2

>例えば、メインのルーチンを実行中に、フォーム上のボタンを押せるようにするにはどうするか等・・・。 その「メインのルーチン」というのをバックグラウンドで動かせばいいです。

goo-learner
質問者

お礼

有難うございます。 バックグラウンドで動かすためにNo1さんのご回答にあったBackgroundWorkerコンポーネントを使うわけですね。トライしてみます。

goo-learner
質問者

補足

質問者です。 ご回答をヒントに所望のプログラムを作成することができました。 有難うございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • APIイベントを発生させる方法を教えてください。

    自作アプリケーション(WindowsのVB)に、 メールファイルをOutLookソフトからドラッグドロップして、ドラッグドロップのAPIイベントを発生させたいのですが、できずに困っています。 (ちなみに、 OutLookソフトからメールファイルをデスクトップ上へドラッグドロップできます。その、デスクトップ上のメールファイルを、自作アプリケーションへドラッグドロップすると、ドラッグドロップのAPIイベントが発生します。) FormのLoadイベントで、2個のAPI関数を実行しています。 (1)サブクラス化開始    Call SubClass(フォーム名.hwnd) (2)フォームがドロップファイルを受け入れるよう設定    Call DragAcceptFiles(フォーム名.hwnd, True) どなたかアドバイスをお願いします。

  • VC++2005 Expressでドロップ検知出来ません

    お世話になります。 WindowsXPで、VC++2005 Expressを使い始めました。 試しにドラッグ・アンド・ドロップ機能をテスト。Form1上にtextBox1を配置しただけのウィンドウです。Form1のAllowDropをTrueに設定してビルド、実行。 テキストファイルをドラッグアンドドロップしても、Form1上にマウスポインタが乗った瞬間、進入禁止のアイコンです。 これはバグなのでしょうか? 同様のご経験のある方いらっしゃいましたら、ご教示よろしくお願いします。

  • 各イベントの共通の前処理は存在する?(VB.NET)

    VS.NET2003,VBについての質問です。 ASP.NETでは、WebControlsのイベントを発生させるたびに(ボタンを押したり、テキスト変更したりなど)、 Page_Load>WebControlsイベントの順番で、イベントが発生することを確認しました。 Windowsアプリケーションにおいて、上記のPage_Loadに該当するイベントは存在するでしょうか。 つまり、Windows.Formsコントロールのイベント処理が発生するたびに、その前処理として実行される、上記のPage_Loadのような共通のイベントは存在するでしょうか。 以上、どうぞよろしくお願い致します。

  • 文字列入力でイベント

    VisualBasic2008(VB.NET)を使っています。 アプリケーションの実行中に、指定した文字列の入力があると、イベントを起こすにはどうすれば良いでしょうか。 (例)アプリケーション実行中に「4649」とタイプするとForm2が開く

  • Perlでイベント処理?

    ようやくPerlに慣れてきて、ふと思ったのですが VBではイベントというものがあり、Perl Tkでもキーボード・マウスのイベントの処理ができる みたいですが、クライアントでソケット受信した場合、いつ受信するかわかりませんので ループしていれば良いのですが、ループしている間は、他の実行が何も出来ず効率も悪いなと 思うようになりました。 WindowsのPerl5.6を使っているのですが、ソケット等、イベント処理できる方法はあるのでしょうか?

    • ベストアンサー
    • Perl
  • ManualResetEvent非同期処理で固まらないようにする

    HttpWebRequestの非同期処理からデータを取得する際に ManualResetEventで完了したかどうかを待機していますが、 待機中はフォームが固まってしまいます。 非同期処理のIAsyncResult中にApplication.DoEvents();をしたら、 例外処理として落ちてしまいます。 ManualResetEvent非同期処理で固まらないようにするには、 マルチスレッドでイベントを起こすしかないのでしょうか? それともほかにいい方法があるのでしょうか?

  • 他フォームのクリックイベント取得

    VS2005を使ってちょこちょこプログラムの勉強をしています。 現在、同一ソリューション内のフォームの間のイベントを実装出来なくて困っています。 やりたい事は Form1から、Form2を起動し、Form2のボタンをクリックした時に、 Form1でForm2のクリックイベントを取得したいのです。 自分なりに調べてみましたが、該当するようなところが中々見つかりませんでした。 わかる方いましたら、ご教示お願いします。 足らない情報等ありましたら、ご指摘ください。

  • VBAのイベント処理について

    VBAのイベント処理について お世話になってます。現在、VBAでアプリケーションを作成しています。 1つのフォームに4つのテキストボックスと1つのボタンが配置されており、それぞれイベントが設定されています。 その中のテキストボックスに関するイベントなのですが、1つのテキストボックスに対してKeyPress、KeyDown、MouseUp、AfterUpdate、以上4つのイベントを作成します。 フォームに配置されている4つのテキストボックスすべてに、上記で示したイベントを作成する必要がありますが、各イベントにおける処理の内容はオブジェクト名が違うだけで全く同じです。 ひとつひとつイベントを作成していけば、処理目的は満たせそうですが、ソースがかなり長くなってしまいます。ひとつのオブジェクトに対してこれらの処理をひとまとめにする様な記述方法はありませんでしょうか?考え方だけでも教えていただければ幸いです。 質問が長くなってしまい申し訳ありません。回答宜しくお願い致します。

  • PictureBoxのMouseUpイベントを意識的に発生させる方法

    VB.Netで開発しています。 表記の通り、PictureBoxのMouseUpイベントを意識的に発生させる方法はありますでしょうか? 具体的な処理の流れは PictureBox1をドラッグ&ドロップすることで ドロップされた位置によって処理を行っているのですが 制限時間をタイマーで設けていて、制限時間が来たら 現在の位置でドロップ(MouseUp)したいのです。 どなたかいい方法ご存知の方いましたらアドバイスお願いします。

  • DragEnterイベントについて(VS2008、ドラッグ&ドロップ)

    VisualStudio2008 C# で開発をしています。 ListViewにエクスプローラーからファイルをドラッグ&ドロップしようとしているのですが、うまくできません。 いろいろと調べて下記の3点を抑えればできるのかと思っていますが、思ったように動きません。 ListViewのAllowDrop=True; DragEnterイベントでe.Effect = DragDropEffects.Copy; DragDropイベントでDropした後の処理 きちんと記述しているつもりですが、DragEnterイベントが発生しません。 ちなみに、同じListViewの要素をドラッグ&ドロップするとDragEnterイベントは発生するので、あくまで外部(エクスプローラーなど)からドラッグされたものが受け付けないようです。 何が原因なのでしょうか? ほかに設定などあるのでしょうか?