C#の開発環境もVSCodeで (DelegateとInvoke)
Back
Alt+HOME
長い仕事、待ち仕事は別のサブスレッドに任せて、メインスレッドはレスポンス良く反応してくれる・・為に記述せねばならないスレッド間通信が私には余りにも難解。取り敢えずメモって間違いに気づいたら直していこうと思う。
- Delegate
- ビジネスにおいて、マネージャやリーダが他の人に業務や責任を委譲する。
他のメソッドを代理で呼び出すための型のこと。
- Invoke
- 措置の発動、権利の行使、策の実施など行動を起こす。
関数ポインタを別スレッドに投げる。コントロールのメソッドであるInvokeは、そのコントロールの属するスレッドで、投げられた関数を実行する。
サブスレッド起ち上げ時のスレッド間処理(Delegateを要する実例)
private void StartKissThread()
{
Thread kissThread = new Thread(() =>
{
// 接続情報チェックをした上でポートに接続を試みる処理
bool isConnected = TryConnectToPort();
bool isPortSet = PortCheck();
string msg = isConnected ? "Connected to KISS Port." :
isPortSet ? "KISS Port is incorrect or TNC is not running." :
"Setup the KISS Address and/or the Port.";
Color color = isConnected ? Color.Green :
isPortSet ? Color.Red :
Color.Red;
UpdateLblMsgCallback(msg, color);
// サブスレッドで受信データの処理をする
if (isConnected)
{
StartClient();
}
});
kissThread.Start();
}
このロジックはサブスレッドを起ち上げる過程において、ポート接続を試した上でその結果をUIスレッドのラベルにコールバック関数を使って書き込むもの。
- TryConnectToPort() を呼び出して接続完了したか否かを判定 isConnected = true or false
- PortCheck() を呼び出して、①接続情報が設定されているか、②設定はされいないかをチェック。
①isPortset = true ②isPortset = false
- この時の組合せの評価方法は・・
- 接続完了(isConnected:true)
- "Connected to KISS Port."
- Color.Green
- 接続不可(isConnected:false)
接続情報有り(isPortSet:true)
- "KISS Port is incorrect or TNC is not running."
- Color.Red
- 接続不可(isConnected:false)
接続情報無し(isPortSet:false)
- "Setup the KISS Address and/or the Port."
- Color.Red
private bool TryConnectToPort()
{
// Settingsからアドレスとポートのデータを読む
string addr = frmSettings.TxtKISS_Address.Text;
string port = frmSettings.TxtKISS_Port.Text;
// 接続に使用する情報を定義
string kissAddr;
int kissPort;
// 接続情報が設定されていたとき
if (addr.Length != 0 && port.Length != 0)
{
kissAddr = addr; // string同士で代入の必要性は無い
kissPort = int.Parse(port);
}
else
{
return false; // PortCheckと同じ結果だがあくまでこのメソッドの結果
}
// ポート接続のロジックを実装
try
{
client = new TcpClient(kissAddr, kissPort);
return true; // 接続された
}
catch (Exception)
{
return false; // 接続情報以外の理由で失敗
}
}
// Settingsの接続情報が設定されているかのチェック
private bool PortCheck()
{
string addr = frmSettings.TxtKISS_Address.Text;
string port = frmSettings.TxtKISS_Port.Text;
// アドレス・ポートのどちらか又は両方が設定されていない
if (addr.Length != 0 && port.Length != 0)
{
return true;
}
else
{
return false;
}
}
- この評価結果に基づいてサブスレッドの状況をUIスレッドのラベルに色を変えてメッセージを表示する。
この時そのまま LblMsg.Text = "Message"; LblMsg.ForeColor = color; 等と記述しても、
この判定を行っているスレッドからラベルが定義されているUIスレッドへ直接アクセス出来ない。
Delegate型の宣言とDelegate型のコールバック関数
public FrmMain()
{
InitializeComponent();
// このフォーム自体のインスタンス
instance = this;
}
// サブスレッドにおける代理メソッド
public delegate void DelegateUpdateLblMsg(string msg, Color color);
// ラベル変更に関するコールバック
public static void UpdateLblMsgCallback(string msg, Color color)
{
if (instance != null)
{
if (instance.InvokeRequired)
{
// Invoke処理が必要な場合
instance.Invoke(new DelegateUpdateLblMsg(instance.UpdateLblMsg), [msg, color]);
}
else
{
instance.UpdateLblMsg(msg, color);
}
}
}
// ラベルの変更
private void UpdateLblMsg(string msg, Color color)
{
if(LblMsg.InvokeRequired)
{
Invoke(new DelegateUpdateLblMsg(UpdateLblMsg));
return;
}
LblMsg.Text = msg;
LblMsg.ForeColor = color;
}
Back
Alt+HOME
この 作品 は
クリエイティブ・コモンズ 表示 - 非営利 - 改変禁止 4.0 国際 ライセンス
の下に提供されています。
English
Powered by