ラベル マルチスレッド の投稿を表示しています。 すべての投稿を表示
ラベル マルチスレッド の投稿を表示しています。 すべての投稿を表示

2013-11-02

BackGroundWorkerによる別スレッドからUIクラスにアクセスする

過去記事にて、C#でマルチスレッドを実現するBackGroundWorkerというコンポーネントを紹介しました。スレッドクラスを利用した処理に比べてシンプルなコードになる利点がありましたが、実際に使ってみてさらなる利点に気づきました。

マルチスレッド処理のUIアクセスの制約
マルチスレッド処理をする際の困難さの1つに、プロセス間通信の制約があります。つまり、スレッドが異なる処理のデータの授受には制約があるということです。この制約の影響をモロに受けるのが、UIコンポーネントです。起動したスレッドから呼び出しものにあるUIコンポーネントにデータを渡す、、例えば、ラベルに値を表示するなどの処理は原則できません。Invorker経由でメソッドを呼び出さないといけません。これでなんら問題なければいいんですが、先日、某サードパーティ製のUIクラスを利用する時に、うまく呼び出すことができませんでした。正確に言うと、Invorker経由で呼び出すと動作が異常に遅くなるのです。もともとthreadクラスを利用していたのでその時は問題なかったのですが、今回、BackgroundWorkerを利用するとダメという、、、意味不明なことに。。。

ProgressChangedイベントが肝!
で、ネットをいろいろ調べてみると、ProgressChangedイベント内ではInvokerが不要であるということが判明しました。正直理屈のわからない話ですが、実際に試してみると、InvorkerなしでUIクラス(Labelクラス)にアクセスすることができました。ProgressChangedイベントを呼び出すためには、
  • WorkerReportsProgressプロパティをtrueにしておく
  • ReportProgressメソッドを呼び出す
という手順が必要です。この方法により、Invorkerを使わなくてよく、さらにUIへの処理を分離できるので、コード的にスッキリします。


2013-09-27

C#:BackGroundWorkerコンポーネントを利用したマルチスレッド処理

C#には、マルチスレッドを実現する方法として、BackGroundWorkerというコンポーネントが用意されています。このコンポーネントをフォームに貼り付けることで、容易にマルチスレッドなプログラムを実現できます。以下、サンプルコードを載せますが、ポイントを挙げておきます。

1.フォームにBackGroundWorkerを貼り付ける
タイマーコントロールと同じような感覚で貼りつけてください。1つのコントロールで1スレッドです。

2.開始と終了
  • 開始 ・・・ RunWorkerAsync()
  • 終了 ・・・ CancelAsync();
のメソッドを呼ぶだけです。

3.スレッド関数
コンポーネント変数名_DoWorkで終わる関数が実行されます。CancellationPendingの値を条件としたスレッドループを記述するのがベターなやり方でしょう。

4.途中と終了の処理
_RunWorkerCompletedと_ProgressChangedというメソッドが用意されていて、それぞれ終了時と途中の任意のタイミングで呼び出されます。呼び出しは明示的にしないとダメです。ReportProgressメソッドは引数がint型で進行状態を表す数値を渡すことが正しい使い方です(下記サンプルは違います)。なお、これらのメソッドを使えるようにするには、これらの処理を有効(true)にしておく必要があります。デフォルトはfalseなので注意して下さい。

InvokerとDelegate
マルチスレッドプログラムにおいては、プロセス間のデータの授受が厄介な問題となります。BackGroundWorkerを利用する方法でも、この問題を避ける事ができません。具体的に言うと、異なるプロセス間の変数には直接アクセスすることができないということです。下記の例では、別スレッドでカウントしている値をラベルコンポーネントに表示する際に、直接ラベルに値を代入できないということです。メソッドを用意してそれをDelegateに渡し、Delegateを介してInvoke(起動)する必要があります。(もっとよい方法が見つかりましたので、くわしくは続編を!



2011-10-28

[C#]スレッドプログラミング

C#でマルチスレッドプログラミングをする方法です。記述自体は特になにも難しいことはありません。 なお記述は簡単ですが、マルチスレッドのプログラミング自体は難しいです。安易に考えていると予期しない動作をすることがあるので注意してください。 また、スレッドにデータを渡す方法ですが別スレッドで呼び出すメソッドに引数などを定義することはできません。一番簡単な方法は同一のクラス内でマルチスレッドのメソッドを定義しているのであれば、クラス変数を利用してデータの授受をすることは可能です。 本格的にプロセス間通信をする場合はちょっとひと工夫必要ですので、それは後日取り上げたいと思います。