投稿者 YuO  (社会人) 投稿日時 2011/12/4 00:24:23
> 例えばForm1でLoadイベントの中でSystem.Threading.Thread.Sleep()を使用しているとき、指定した時間内はForm1が表示されることはありませんよね。

まず,UIスレッドを止める行為自体が「やってはいけない」ことです。
イベントを止めているつもりかもしれませんが……。

イベントハンドラの処理は,UI全体で一つのスレッドしか使われません。
そんとあめ,UIを処理するスレッドでSleepした場合,UIに関する処理が全てストップします。

時間がかかるなら,別にスレッドを立てて,そちらを経由します。
まぁ,現状自分でThreadクラスを使うことはなく,BackgroundWorkerとか,Taskとか,デリゲートのBeginInvokeとかで済ましますが。


> それを別のフォーム(Form2)でクリックイベントが発生したらForm1のLoadイベントを中止(所謂Exit Sub?)
> してForm1が表示するように干渉させることは可能なのでしょうか?

UIスレッドを止めていますから,不可能です。
# 別途STAなThreadを先に作ってそちらで呼び出していればできなくもないのですが……。

・BackgroundWorkerの場合 (時間のかかる処理が一つだけで再入しない場合に有効。少数であれば,複数BackgroundWorkerを用意してもよい)
WorkerSupportsCancellationプロパティを事前にTrueにしておく
UIスレッドからはCancelAsyncメソッドを呼び出す
ワーカースレッド(=DoWorkのイベントハンドラ)はCancellationPendingプロパティを時々見に行き,CancellationPendingプロパティがTrueであれば,e.CancelをTrueにしてスレッドを抜ける

MSDN: WorkerSupportsCancellation プロパティ
http://msdn.microsoft.com/ja-jp/library/system.componentmodel.backgroundworker.workersupportscancellation.aspx
MSDN: CancelAsync メソッド
http://msdn.microsoft.com/ja-jp/library/system.componentmodel.backgroundworker.cancelasync.aspx
MSDN: CancellationPending プロパティ
http://msdn.microsoft.com/ja-jp/library/system.componentmodel.backgroundworker.cancellationpending.aspx

・Taskの場合
CancellationTokenSourceのインスタンスを用意しておく
用意したCancellationTokenSourceインスタンスのTokenプロパティを使ってTaskを生成しておく
UIスレッドからはCancellationTokenSourceインスタンスのCancelメソッドを呼び出す
ワーカースレッド(=Taskの引数のデリゲート)では定期的にCancellationTokenSourceインスタンスのTokenプロパティのThrowIfCancellationRequestedメソッドを呼び出す

MSDN: CancellationTokenSource コンストラクター
http://msdn.microsoft.com/ja-jp/library/dd321699.aspx
MSDN: Task コンストラクター (Action, CancellationToken)
http://msdn.microsoft.com/ja-jp/library/dd783029.aspx
MSDN: Cancel メソッド
http://msdn.microsoft.com/ja-jp/library/dd321955.aspx
MSDN: ThrowIfCancellationRequested メソッド
http://msdn.microsoft.com/ja-jp/library/system.threading.cancellationtoken.throwifcancellationrequested.aspx

・BeginInvokeの場合
キャンセルの為の標準的な手段は用意されていないので,自分で用意する必要があります。