CUIとGUI
GUIの場合は、「ボタンを押したらどうするか」を決めて、そのまま全処理を終了する。そしてボタンが押されるのを待ち、ボタンが押されると新たな処理が起動する。
CUIの場合というわけではないが、たとえばscanfとすると、処理が止まる。入力されるのを待って、入力を受け取り次の処理に進む。
見た感じどっちが分かりやすいかといえば後者だ。GUIでもダイアログを開く場合には処理が止まる。
1番と2番、どちらを選ぶかを決めるコードを書いてみる。
//止まる版 void Select() { int a = Read(); switch(a) case 1: Hoge1(); case 2: Hoge2(); } //止まらない版 void Select() { button1.Clicked += Hoge1; button2.Clicked += Hoge2; }
止まる版の一番の問題は、呼び出されたHogeの中で再びSelectが呼び出せないことだ。HogeがSelectを呼び出し、またHogeがSelectを呼び出し・・・と続けていくと、無限ループになりいずれスタックが溢れてしまう(ものすごい時間がかかるだろうけど)。しかしHoge()から呼び出される先でSelect()を呼び出さないという制限を課す確実な方法がない。
止まらない版の、全処理を終了することでしかこれが実現できない。それか決して呼び出されないMainメソッドまでreturnするか。
止まる版と止まらない版のinterfaceを共通にしたい。scanfで選択する場合とGUIで選択する場合を同じように使いたい。しかし使われ方が全く違う。普通にやると実行順序が確実に変わってしまう。
こんな感じかな。
void Select(Action hoge1, Action hoge2) { Thread current = Thread.CurrentThread; new Thread( () => NewThread(current, hoge1, hoge2) ).Start(); } void NewThread(Thread current, Action hoge1, Action hoge2) { //呼び出し元の処理を全部終わらせる current.Join(); int a = Read(); switch(a) case 1: hoge1(); case 2: hoge2(); }
どっちにせよ呼び出し元の処理が先に終わる形に揃える感じで。