UWSCのスレッドを停止する

以前公式掲示板に、「スレッドの一時停止について」という投稿があった。
http://www3.bigcosmic.com/board/s/board.cgi?id=umiumi&mode=all&no=4952&log=ON&cnt=41
メインスレッドを一時停止する方法を尋ねるものでした。
改めてスレッドを止める方法を考えてみた。


結論としては、銀の弾はない、ですが、、、。



提案した方法

メインスレッドを一時停止したい、とのことなので、MSGBOXを出す方法を提案しました。
こんな感じ。

THREAD Loop("sub")
THREAD Watch()
Loop("main")

PROCEDURE Loop(msg,wait=1)
	WHILE TRUE
		GETTIME()
		PRINT G_TIME_SS2 + " " + msg
		SLEEP(wait)
	WEND
FEND

PROCEDURE Watch()
	WHILE TRUE
		IF GETKEYSTATE(VK_ESC) THEN MSGBOX("Stop")
		SLEEP(0.1)
	WEND
FEND

ESCキーを「ちょん」と押すと、MSGBOXが出てメイン側が止まるのがわかります。
監視用スレッドは止まりますが、サブ側Loopは止まりません。
MSGBOX以外にINPUTやSLCTBOXでも同様です。
ほとんどバッドノウハウであり、いつ仕様変更があってもおかしくないですが、今は止まるのです。


じゃあ、正攻法は?と考えた時、Win32APIを使うアイデアは微妙。
SuspendThread/ResumeThreadは、メインスレッドに使うのは非常に危険に思える。
UWSCのメインスレッドは、管理を行っていると思われるため
ちなみに、サブスレッドに使うのも危険でしょう。
→サブスレッドが不自然に止まっているとUWSCがロックする模様。長時間止めるのは危険
デバッグ中くらいしか使えないかと思います。


となると、今のところ正攻法はなさそう。
考え方を変える。

忙しいなら処理しない

スレッドのプライオリティを下げてはどうでしょう。
メインスレッドにやるのはちょっと危険な気がしますが、サブなら良いかと。

DEF_DLL SetThreadPriority(DWORD,int): BOOL: kernel32
DEF_DLL GetCurrentThread(): DWORD: kernel32

THREAD Loop("sub", 1, -15)
Loop("main", 0.001)

PROCEDURE Loop(msg,wait=1,p=0)
	IF p THEN SetThreadPriority(GetCurrentThread(), p)
	WHILE TRUE
		GETTIME()
		PRINT G_TIME_SS2 + " " + msg
		SLEEP(wait)
	WEND
FEND

メイン側が「がーっ」と出て、サブは少しになるかと思います。

実態にあわせて止める処理を書く

確かに、全ての処理に停止するコードを入れるのは、面倒です。
でも、本当に全ての箇所で必要でしょうか?
パレートの法則というのがあります。


人間(とろい)が止めたいと思った瞬間、その瞬間にもUWSC(はやい)は動いています。
例えばスレッドの処理ががーっとあっても、実際に止められる瞬間は、固定していませんか?
例えば負荷軽減のためのSLEEPとか、GETIDとか。
そこに一時停止する処理をさくっと入れましょう。

WHILE GETKEYSTATE(VK_ESC); SLEEP(0.1); WEND

こんなのも良いですね。

IF GETKEYSTATE(VK_ESC) THEN MSGBOX("一時停止中")

ただこれをサブでやると、前述のようにメインスレッドも停止します。