C#のdelegate

ある趣味プロでC#delegateを初めてまともに使うことになったので、メモ。
誤解を恐れずにいえば、C#におけるdelegateは、非同期通信を利用するためのものだ。
例えば、ワーカースレッドから親スレッドのメソッドを呼び出したい場合や、複数のイベントハンドラを使用する場合だ。
教科書には、ポインタの使用に明示的な宣言が求められるC#で、宣言無しに「C#で関数ポインタが使用できる」方法となっている。
んじゃどんな場合に使うのよ?となると上のような場合だ。


手順としては、

こんな感じだ。


delegate void DelegateShowAho();

void showAho()
{
MessageBox.Show("Aho");
}

private void btnAho_Click(object sender, EventArgs e)
{
DelegateShowAho delegateShowAho = new DelegateShowAho(showAho);
delegateShowAho();
}

引数を渡すときには、以下のようになる。

delegate void DelegateShowAho();

void showAho(string stringMessage)
{
MessageBox.Show(stingMessage);
}

private void btnAho_Click(object sender, EventArgs e)
{
DelegateShowAho delegateShowAho = new DelegateShowAho(showAho);
delegateShowAho("Aho");
}

同一スレッド内では、全く意味がないことだ。
しかし、これが異なるスレッドで動作しているメソッドを呼び出す場合には意味があることだ。
例えば、SerialPortのDataReceivedメソッドは、一つのワーカースレッドとして動作する。
SerialPortをFormに配置したとしても、このメソッドからFormのメソッドを呼び出すことはできないのだ。
こんなときにdelegateを使用する。

private void onSerialPortReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
int ReadByteSize = serialPortTest.BytesToRead;
byte[] ReadBuffer = new byte[4096];
serialPort.Read(ReadBuffer, 0, ReadByteSize);
string stringRXMsg = Encoding.GetEncoding("Shift-JIS").GetString(ReadBuffer, 0, ReadByteSize);
// for thead to thead communication
DelegateUpdateMsg delegateUpdateMsg = new DelegateUpdateMsg(updateRXMsg);
this.Invoke(delegateUpdateMsg, stringRXMsg);
}

private delegate void DelegateUpdateMsg(string RXMsg);

private void updateRXMsg(string RXMsg)
{
tbRXMsg.Text += RXMsg;
}

ちなみに上記の"this.Invoke(delegateUpdateMsg, stringRXMsg)"だが、TextBoxのインスタンスであるtbRXMsgを使って、"tbRXMsg.Invoke(delegateUpdateMsg, stringRXMsg)"としても動作する。
どのインスタンスInvokeを使うかで、どのインスタンスのスレッドを利用して、このdelegateを実行するかを決めるからだ。
http://msdn.microsoft.com/ja-jp/library/a1hetckb%28v=vs.110%29.aspx