C# .NETプログラミングメモ(その2)
さてさて。(その1)が思ったよりも馬鹿長いエントリになってしまったので、もう一つメモしておきたいことをこちらへ書いておきましょう。
(その1)ではめでたく外部クラスからイベントを発生させ、イベントの中身にデータを持たせることで、フォーム側に値を渡す事が出来ました。では、あとは、その受け取ったデータをそのままFormの…そう、例えば、richTextBox.Textに直接突っ込めるかというと、それが出来ない場合が。
どういった場合に出来ないかというと、スレッド間をまたいでしまうときのようです。
混乱しがちなのですが、
一本のスレッドで動いている上でイベントを発生させて、Form側で受信した時は、直接アクセス可能。
マルチスレッドや、非同期ソケット等で、複数のスレッドに分岐した先でイベントを発生させて、Form側で受信した時は、直接のアクセスが不可。
という感じでしょうか?
じゃあ、それをどうやって回避するかというと、(ここではrichTextBox.Textへの代入を例とします)Form側に、
delegate void LogWriteDelegate(string s);
と、なんか最近見飽き始めてきつつあるdelegateを宣言し、
public void LogWriteInvoker(string s)
{
if (InvokeRequired)
{
Invoke(new LogWriteDelegate(LogWriter), new object { s });
return;
}
else
{
LogWriter(s);
}
}
この、if(InvokeRequired)のブロックが、別スレッドからこのメソッドを呼ばれた際の動作です。
よって、elseに書くべき物は、同一スレッドから呼び出された際の動作です。
そして Invoke(new LogWriteDelegate(LogWriter), new object { s }); でInvokeした上でデリゲートを宣言。その際にobject[]型でLogWriteInvokerに渡されているstring sも渡しています。
public void LogWriter(string s)
{
richTextBox1.Text += s + "\r\n";
}
そしてここに結びつきます。以上の流れを言語化し纏めると、
同一スレッドから直接アクセスできない物を、同一スレッドからの呼び出しか、別スレッドからの呼び出しかによって動作を変えるメソッドを挟んで、そのメソッド内からInvokeとDelegateを利用して、LogWriterメソッドを叩き、そのメソッド内からは書き換えが可能。となるようです。