delegateとは
関数の呼び出し先を格納する変数。
他クラスから他クラスにメソッドを渡すことができる。
delegateは主にC#の非同期処理やコールバックとして使われる。
なぜdelegateを使うのか
クラス同士のやり取りは通常一方方向。
例えばメインクラスでサブクラスのインスタンスを生成し、メインクラスでサブクラスのインスタンスを使うことができる。
しかしサブクラスでメインクラスのメソッドを使おうとしても、サブクラスはメインクラスの存在を知らないため使えない。
そこでサブクラスでメインクラスのメソッドを使うときにdelegateを使う。
基本的な使い方
基本的には以下の手順で実装可能。
①サブクラスでdelegate定義、delegate変数を定義
②メインクラスでサブクラスのインスタンスをnewする
③delegate変数にメインクラスのメソッドを代入
④サブクラスでdelegate変数を実行
インスタンス化が難しいとき
メインクラスでサブクラスのインスタンスを生成するときに、引数の問題でインスタンスが生成できない時がある。
その時の解決方法として以下がある。
・引数を新たに作成する
・サブクラスのコンストラクタの引数に新たにdelegate型の引数を追加
引数を新たに作成する方法は、その引数の役割を考えて作成しなければいけないため注意が必要。
delegate型の引数を追加するということは、呼び元(メインクラス)のメソッドを引数で持っていき、コンストラクタ内でdelegate変数にメソッドを代入する方法。
この方法は他でインスタンスを生成している場合は注意が必要。
UIスレッドに処理を投げる
テキストボックスやラベルなどのコントロールは、UIスレッドでしか操作することができない。
別スレッドでコントロールを操作したいときは、その処理だけUIスレッドに投げることで操作が可能。
それぞれのアプリケーションでUIスレッドへ処理を渡す仕組みは異なるため、使用するクラスは異なる。
WindowsフォームアプリではSystem.Windows.Forms.ControlのInvoke()、WPFではSystem.Windows.Threading.Dispatcher、UWPではWindows.UI.Core.CoreDispatcherを使用する。
基礎学習 × .NET Framework の非同期処理を見直してみた × その4
Invoke
Invokeはスレッドを新しく生成し、そのスレッド内でコントロールなどのオブジェクトを操作する際に呼ぶ。
Invoke()は主にWindowsフォームで使われる。(WPFでも使える)
サブスレッドでInvokeを実行すると、Invoke内の処理はメインスレッド内で実行される。
以下のサイトがわかりやすかった。
【C#】UIスレッド以外からUIのコントロールを操作する
またInvokeはコントロールのオブジェクトが存在するクラスでしか呼び出すことができない。
delegate変数に入れたメソッド内でコントロールの操作がしたい場合、そのメソッド内でInvokeRequiredをすることで実装できる。
InvokeRequiredはそのスレッドがサブスレッドの場合はtrue、メインスレッドの場合はfalseになる。
つまりInvokeの実行が必要かどうかを返す。
InvokeRequiredがtrue(サブスレッド)の場合は、Invokeの実行が必要なためInvokeを実行するように書いてあげる。
[C#]Invokeの引数の使い方とは?InvokeRequiredプロパティ
Action,Func
delegateの宣言、インスタンス化、メソッド代入を省略した構文のこと。
- Action→戻り値なしのもののみ
- Func→戻り値あり
参考サイト:【C#】delegate, Action, Funcについて 多分一番易しい解説
ラムダ式
一回の実行であるならば定義は必要がないもの。
参考サイト:【C#】delegate, Action, Funcについて 多分一番易しい解説
Task,async/await
Task=非同期 ではない。
Taskは処理としてとらえるとわかりやすい。
awaitは、タスクの処理の完了を待つ。同期処理のような感じになる。
Taskを極めろ!async/await完全攻略