• ベストアンサー

C#のマルチスレッド処理について

C#のWindowsフォームアプリケーションをつくっています。 .Netではマルチスレッド関連の選択肢がたくさんあるようですが、以下のようなユースケースではどんな組み合わせにするのがいいのでしょうか? UIとは別スレッドでネット接続してデータとってきたものをフォームに反映します。UIはブロックして欲しくなくて、ローディング中にはローディング中にアニメーションを表示したりします。 新スレッドを作って、その完了を待つことはできるんですが、その結果をどうフォームに反映するか、というところがよくわかりません。 C#は初心者なのでコード例やリンクをよろしくお願いいたします!

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

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

C#付属の MSDNでBackgroundWorkerの概要などが参考になると思いますよ BackgroundWorkerオブジェクトを作成して DoWorkイベント、ProgressChangedイベント、RunWorkComplatedイベントのハンドラを記述 実際に データを取得する関数を記述 実行開始ボタン、キャンセルボタンのClickイベントを記述 といった具合でよさそうです ProgressChangedイベントでアニメーション処理を行い RunWorkComplatedイベントで取得データをフォーム側での処理をしてやればいいようですよ

参考URL:
http://msdn.microsoft.com/ja-jp/library/system.componentmodel.backgroundworker.aspx
m_i_t_s_u_b_a
質問者

補足

ありがとうございます! なるほどProgressChangedとRunWorkerCompletedイベントでBackgroundWorkerの結果を受け取れるんですね。 この例だと、ある処理をBackgroundWorkerにやらせて結果が終わったらBackgroundWorkerの処理は終了すると思いますが、 UDPのポートをあけて違うPCからのデータを待ったりというのも含めて、BackgroundWorkerは継続的に動作しているイメージで考えているんですが、 そういった場合にもBackgroundWorkerを使うのがよいのでしょうか? ProgressChangedで何度もデータを受け取ればいいのでしょうか。 それぞれのスレッドがキューを持って、メッセージをやり取りするような仕組みとかかなぁってイメージしているんですが。 そういう実装は一般的ではないですか?

その他の回答 (2)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

デリゲートの実装などはBackgroundWorkerを継承したクラスでイベントとして実装した方が良いかと思います イベントとコールバック http://msdn.microsoft.com/ja-jp/library/ms229041.aspx イベントのデザイン http://msdn.microsoft.com/ja-jp/library/ms229011.aspx キューに関しては明るくないので …

m_i_t_s_u_b_a
質問者

お礼

最後までつきあってくださりどうもありがとうございました! いただいたリンク先のコード例を見ながら、なんとかなりそうです。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

BackGroundWorkerでかまわないと思います 継続処理ですと RunWorkComplateイベントの発生は無いと思います 簡易的な実装でよければ ProgressChangedイベントを上手につかってやるか もしくはUDPで受信したデータを引数に取る別のデリゲートを設けて UDPの受信処理の区切りでデリゲートを呼ぶといった手法になると思います 上記の方法はあまりに大量のデータですとスタックを食いつぶしてしまうなどの弊害が起きる可能性があります メッセージキューなどによる実装でもいいと思いますよ

m_i_t_s_u_b_a
質問者

補足

何度もありがとうございます! >もしくはUDPで受信したデータを引数に取る別のデリゲートを設けて >UDPの受信処理の区切りでデリゲートを呼ぶといった手法になると思います こちらは、Invokeを使ってフォームに状態を伝える感じでしょうか? メッセージキューを使った実装例の参考ページやコード例等ございますか?

関連するQ&A

  • マルチスレッドでブレイクポイントするとフリーズする

    C++/CLI .Net2008 windowsフォームアプリケーション 二つのスレッドが同時に動いているマルチスレッドプログラムを作成しています。 デバッグでブレイクポイントを張って途中で止めたいのですが、止めてすぐもしくはF10で2,3行進めるとフリーズしてアプリが動かなくなってしまいます。他のoutlook等も動かせず、タスクマネージャも開かないため、画面下のウィンドウを右クリック、閉じるを5~10分くらいかけて行って終了させています。たまにVisualStudio自体もフリーズして落ちることがあります。 ブレイクポイントで止めなければフリーズはしません。 プログラムの構成としては、 片方は外部装置からリアルタイムでデータを受信し、判別した結果を出力するスレッドと、その判別結果を元に状態を遷移させるスレッドです。 また、状態によってはタイマーを設けている箇所があり、タイマー処理もスレッドで行っています。 ブレイク張らずに実行した時におかしい動作をしている箇所があるので1行ずつ見たいのですが、マルチスレッド環境ではフリーズするものなのでしょうか?

  • マルチスレッド化。

    今とても大きな配列を使用し、長時間処理をするプログラムを組んでいます。元々処理時間に1時間を要するプログラムを2分で処理を完了するまでに仕上げました。 しかし、探究心はおさまらずもう少し高速化に挑みたいと考えています。 過去に「猫でもわかる」のSDK第1章と2章を学び、マルチスレッドのプログラムをSDKで組んだことがあります。それを利用してマルチスレッド化を実現したいと考えています。 言語はCでVisualStudio2005を使用しています。 *疑問1   SDKの場合WinMain関数とプロシージャからの実行で_beginthread関数を記述すれば処理が開始されます。 Cでもmain関数内に記述すれば、SDKと同様に処理できるのでしょうか? *疑問2 _beginthread関数の引数に関してです。 第1引数にvoid型のスレッド関数、第2引数に0?、そして第3引数にはスレッド関数に渡すデータの引数を記述すると把握しているのですが、渡したいデータは複数あり、***型と**型、それに変数を数個とスレッド関数に渡したいデータだらけなのですが、どのように記述すればよいでしょう? *疑問3 2つのスレッドを作成しようと考えていますが、その2つのスレッドで1つの大きな配列を共有して処理したいと考えています。 そのため、スレッド間の同期が必要になるわけですが同期の種類にもクリティカルセクションやミューテックス、イベントと豊富でどれを使用すれば良いのか迷ってしまいます。厳密に同期を取り処理をするにはイベントが一番良いと考えています。 これらの疑問に答えられる方はアドバイスをよろしくお願いします。

  • VB.NET開発(イベントプロシージャはマルチスレッドですか?)

    VB.NET開発(イベントプロシージャはマルチスレッドですか?) 以前より.NETのWindowsフォームの業務アプリ開発してますが、基本的な質問をさせて下さい。 イベントプロシージャの実行処理は、本体スレッド(実行時のスレッド)とは別のスレッドで動作しているのでしょうか。 例えば、ボタンのクリックイベントに何かしらの重い処理があったとします。このクリックイベントの処理ではボタンの制御をしていないので、イベントプロシージャの実行中は、処理中のボタンが押下可能な前提とします。この時、このボタンを3回押下して実行させると3つのスレッドが新規に作成されて実行していると考えて宜しいのでしょうか。 デリゲートやイベントに関するキーワードで検索して、いくつか資料を見たのですが、上記の疑問にぴったり合う解答がなく、質問させて頂きました。 業務アプリの開発で、今まで、あまりマルチスレッドなど意識せずやってきましたが、実は意識しなくても、マルチスレッドの開発をしていたことになるのでしょうか。 以前、VB6の開発もしておりました。 ちなみにVB6の場合も、イベントプロシージャはマルチスレッドで実行されていると考えて宜しいのでしょうか。 よろしくお願いします

  • ローディング画面をマルチスレッドで動かせません。

    ローディング画面をマルチスレッドで動かせません。 DirectXとC++をVisualStudio2010でゲームを制作しています。 ローディング画面を動かせるようにマルチスレッドにしているんですが、パソコンによってはローディング画面から動かなくなってしまいます。(開発環境では、問題なく動きます) スレッドの呼び出し部分は以下のようになっています。 HANDLE thread; CScene gamen; //タイトル画面やメインゲーム画面などのシーンを管理 void Loading() { SetDrawLoading( true ); delete gamen; gamen = new CTitleGamen(); thread = (HANDLE)_beginthreadex(NULL,0,DrawLoading,NULL,0,NULL); gamen->LoadData(); //クラス内の画像や音楽データを読み込み effect->SetDrawLoading(false); WaitForSingleObject( thread, INFINITE ); CloseHandle(thread); } マルチスレッド部分は以下のように、 drawLoading変数がtrueの間、ローディング画面を描画するようにしています。 D3DXMATRIX m_world; unsigned __stdcall DrawLoading(void *p){ LPDIRECT3DTEXTURE9 pTexture; D3DXCreateTextureFromFileEx(m_pD3DDevice, TEXT("texture.png"),16, 16, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT, D3DCOLOR_XRGB(255,255,0), NULL, NULL, &pTexture)) do{ m_pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); if( SUCCEEDED( m_pD3DDevice->BeginScene() ) ) { D3DXMatrixIdentity( &m_world ); m_pD3DDevice->SetTransform( D3DTS_WORLD, &m_world ); m_pSprite->Begin( D3DXSPRITE_ALPHABLEND ); m_pSprite->Draw( pTexture, NULL, NULL, &D3DXVECTOR3( timeGetTime()%800), 550, 0 ), 0xffffffff ); m_pSprite->End(); m_pD3DDevice->EndScene(); } m_pD3DDevice->Present( 0, 0, 0, 0 ); }while( effect->GetDrawLoading() ); pTexture->Release(); _endthreadex(0); return 0; } どなたか、ご教授お願い致します。

  • マルチスレッドの疑問点と配列について

    こんばんわ。 VC++.NET2003を用いて、C言語プログラミングを行っています。以下に質問内容をまとめます。 1.現在、マルチスレッドを行っています。マルチスレッドの注意点として、 ・スレッドが複数同時に処理(現在2スレッド)され、それぞれのスレッドで同一のグローバル変数をアクセスする。 ・各スレッドで使用しているスタティック変数はプロセスとして1つの領域に確保される。 と記述されていました。 現在、2スレッド動かしているのですが、2スレッド共通で使用したい変数がある場合は、グローバル変数として宣言してよいのでしょうか? スタティック変数というのは、 static int i を指すのでしょうか・・・・初心者的発言で申し訳ありません。 次にもう一つ質問させていただきます。 配列を整数型で10000要素、静的に用意します。 これを、memset関数ですべての番地に0を初期値として入れておきます。 たとえば、9000という数字があった場合、9000番に整数値9000を格納する。また、56では56番に56を格納する。 そして、最終的に10000要素を走査し0の場所をカウントする。 ということは可能でしょうか?もしよろしければ、サンプルを教えていただきたいと思っています。 よろしくお願い致します。

  • タイマー関数とマルチスレッドについて

    こんばんわ。 マルチスレッドプログラミングを行なっています。 コンパイラはVC++.NETでC言語を利用しwin32 apiを用いています。 スレッドを_beginthreadex関数でスレッドを2つ生成し、WaitForSingleObject,SetEvent,ResetEvent関数によるイベント同期を利用し、2スレッドの同期をはかっています。 [質問内容] 以下のように、スレッド2でWaitForSingleObject関数にてスレッド2を待機状態にし、スレッド1のSetEvent関数にて待機しているスレッド2を再開させる方法をとっています。 例えば、タイマーをスタート後に待機状態になり、スレッド2が再開後タイマーストップするとした場合、スレッド2が待機状態のときもタイマーを動き続けているのでしょうか? ・スレッド1 SetEvent(hEvent[0]); ・スレッド2 SUSPEND_INTERVAL=20 if(Num%THREAD_SUSPEND_INTERVAL==0){ timestart=timeGetTime();←タイマースタート WaitForSingleObject(hEvent[0],INFINITE); ResetEvent(hEvent[0]); timestop=timeGetTime();←タイマーストップ } よろしくお願いします。

  • ManualResetEvent非同期処理で固まらないようにする

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

  • Visual C++でクラス編集

    Vista上で、MSVS2008EEのVisual C++を使っています。 http://www.microsoft.com/japan/msdn/vstudio/express/ サブスレッドを使用するWinアプリを作ってるのですが、ヘルプに書かれていることができなくて困っています。 ファイル-新規作成-プロジェクトで、CLRのWindowsフォームアプリケーションでプロジェクトを作りました。 フォームデザインで見た目を作った後、スレッドオブジェクトを使おうと、クラス追加をしました。 クラスビューをアクティブにして、プロジェクト-クラスの追加で、C++のC++クラスで名前を入力して追加しました。 ウィザードで、名前Work、基本クラスにThreadを入力して完了ボタンを押しました。 これでクラスビューに追加したクラスが表示されます。 ヘルプでは、メソッドの追加はクラス指定して右クリックのメニューから、とあるのですが、この表示されたものに対して行ってもメニューにそのような項目はありません。 それと、CLRのThreadを認識していない感じもしています。 というのは、クラスビューで階層を見ると、基本クラスのThreadに関する情報がまるでないからです。 何がおかしくて、どうすればいいのでしょうか。

  • C#とC++

    Windowsフォームアプリケーションをつくるにあたって、C++とC#の勉強をし始めましたが、どちらも勉強する必要はありますか? また、一方でいいというなら、どちらがいいですか? 両方なら、なぜ両方勉強したほうがいいですか? 質問責めになり申し訳ないですm(_ _)m 良かったら回答お願いします(つд`)

  • 古いマルチスレッドプログラムはマルチコアに対応しているのか

    Windows上での話という事でお願いいたします。 HTが出始めた頃の高級言語C++やDelphi等で作成した、マルチスレッドプログラムは、そのままでマルチコアに対応しているのでしょうか? 多くの記事やネット上の情報およびインテルのQuad coreのプロモーションを見る限り、プログラムがマルチスレッドならば、そのままマルチコアを有効に利用できるような事が書いてありますが、プログラミングにおいて、特別にマルチコアに対応するようなコードは必要ないのでしょうか? C#用のQuad Core対応といったようなライブラリもあり、特別な処理が必要なのではという雰囲気がただよっているのですが・・・。 (ライブラリのソースまで見れたわけではないので、実態がよくわからない) Quad Core対応のライブラリというのは、いったい何をしていると予想されますでしょうか。 4スレッドで動く事を前提に最適化されているだけなのでしょうか。 といった疑問なのですが、お暇がありましたら ご回答いただければ幸いです。

専門家に質問してみよう