DOBON.NET DOBON.NETプログラミング掲示板過去ログ

別スレッドからイベント通知する方法

環境/言語:[Windows7 .Net Framework 3.5 C#]
分類:[.NET]

はじめまして、森と申します。

シリアル通信でデータを受信した場合イベントとして通知するクラスを
作成し、それを利用するフォームでイベントを受け、フォーム上のコントロール
にイベントで通知されたデータを表示させようとしていますが、クラス側の
イベント生成を別スレッド内で行っているため、フォーム側でコントロールに
アクセスする時に例外が発生してしまいます。
コントロールへのアクセスを Invoke を使用してもやはり例外が発生してしまい
ます。

別のクラスの別スレッドからイベントの使用先で正常に使用(?)できるイベント
を通知するにはどのようにすればよいのでしょうか


public class View : Form
{
private classSerial Serial = new classSerial();

public View
{
Serial.Receive += new classSerial.DelegateReceive(ReceiveProcess);
:
Serial.Start();
:
}

private void ReceiveProcess(string Message)
{
TextBox1.Text = Message;
~~~~~~~~~~~~~~~~~~~~~~~~~ この処理でイベントを発生している
部分 (A) で例外が発生してしまう
}
}

public class classSerial
{
public delegate void DelegateReceive(string Message);

public event DelegateReceive Receive;

private Thread SubThread;

public void Start()
{
SubThread = new Thread(new ThreadStart(ReceiveWorker));
SubThread.Start();
:
}

private void ReceiveWorker()
{
while (true)
{
if ( 受信したら )
{
if (Receive != null)
{
Receive( 受信したデータ );
~~~~~~~~~~~~~~~~~~~~~~~~~ (A)
}
}
}
}
}
2012/02/04(Sat) 20:18:36 編集(投稿者)

ソースコードを貼り付ける場合は図表モードを使いましょう。
通常モードだとインデントがなくなります。

■No29763に返信(森さんの記事)
> コントロールへのアクセスを Invoke を使用してもやはり例外が発生してしまい
> ます。

どのようなコードを書いたのでしょうか?
そして、でた例外はどんなものでしょうか?

以下はコンパイルしていませんが、想定しているコードです。

private void ReceiveProcess(string Message)
{
  if (InvokeRequired)
  {
    Invoke(new classSerial.DelegateReceive(ReceiveProcess), Message);
    return; // return かかないと意味ないので注意。(二度次の行が実行される)
  }
  TextBox1.Text = Message;
}


> 別のクラスの別スレッドからイベントの使用先で正常に使用(?)できるイベント
> を通知するにはどのようにすればよいのでしょうか

ほかには ISynchronizeInvoke のオブジェクトを受け取るプロパティを作っておいて、
そこへ利用者にコントロールのオブジェクトを登録してもらう。
クラス側ではこのプロパティが null でなく、InvokeRequired が true なら、
Invoke でイベントを呼び出す。
そうすることで、利用側で Invoke がいらないクラスにはできます。

# そうするべきかどうかは、クラスの性質などによる。

DOBON.NET | プログラミング道 | プログラミング掲示板