投稿者 YuO  (社会人) 投稿日時 2011/12/4 11:43:17
> コード一つで簡単に出来ることかと思いきや、意外と難しい、というか手順が必要なのですね・・。

先のコードのようになったのは,
・Sleepのような,時間のかかる動作が入っていたので非同期処理にした
・Form1とForm2を一応独立させて,相互に監視するようなことをしないように作った
ためです。
# 後者を気にした割にForm2のForm1LoadRequestイベントとか,名前がおかしいですが。


> >まず,UIスレッドを止める行為自体が「やってはいけない」ことです。
> >イベントを止めているつもりかもしれませんが……。
> これは、本来はSystem.Threading.Thread.Sleep()を使ってはいけない、ということでしょうか?

Sleepを使うのはかまいません。UIスレッドで使ってはいけない,というだけです。

ちなみに,UIスレッドを止める行為はSleepに限りません。
「Sleepを使うこと」ではなく,「UIスレッドを止める行為」をやってはいけない,と書いたのはそのためです。
# 正確には,「UIスレッドを長時間専有する行為」ですが。
わかりやすいものではネットワークアクセスは長時間スレッドを止める代表例になります。
長時間の境はとりあえず50msと考えて下さい。次期Windowsで搭載されるWinRTの同期と非同期の境界となる時間です。

WinRTではファイルアクセスすらも非同期処理になっています。
# まぁ,コンパイラによるAwaitのサポートによってそれほどコード上の違いはなくなるでしょうけれど。


> インターネットのほかのサイトでも普通にSystem.Threading.Thread.Sleep()が紹介されていたり使われていたので必要ならやっても構わないことだと思っていましたが・・。

UIスレッド上でSleepが必要になることがおかしいのだと思って下さい。
UIスレッド上でSleepをする,ということは,「UI自体をSleepする」ことです。
わざわざ「応答なし」にする必要はないですよね。

++C++;の岩永氏の,
> 0.5秒固まったら「使いにくい」、3秒固まったら「バグだ」、10秒固まったら「パソコンが壊れた」と言われる。
http://ufcpp.net/study/csharp/misc_uithread.html
は中々に真実を言っていると思います。

.NET 1.0から既にスレッドプールが,.NET 2.0でBackgroundWorkerが,.NET 4でTaskやPLINQが,
次期VB/C#ではAsync(async)/Await(await)が入るのには,スレッドを簡単に使うための方法でもあります。

ただ,現状Task使うにしてもBackgroundWorker使うにしても,入門で取り扱うには難しい,という問題があります。
そのため,入門系の記事ではこのあたりを取り扱っていない傾向にあります。
# ワーカースレッドからUIを扱うことができない(読み取りであっても)など,UI/ワーカースレッドのどちらかを気にする必要がある。


Taskを使う版のForm1.vbの中身を,例えば
    Private _canceled As Boolean

    Public Sub WaitLoad()
        While Not _canceled
            Thread.Sleep(1000)
        End While
    End Sub

    Public Sub CancelWaitLoad()
        _canceled = True

        Me.Show()
    End Sub
とすると,Form2すら表示されなくなります。
WaitLoad()の中でSleepし続けるためです。

Program.vbでf2.Show()の後にf1.WaitLoad()をするようにして,Sleepの直前にApplication.DoEvents()すれば一応動作しますが,
1000msに1回だけしか処理しないため,ボタンを押すまでの間,動作にタイムラグが発生します。


> 二つの異なるクリックイベント(イベント1とイベント2)があり、片方のイベント(イベント1)が発生したかどうかでもう片方のイベント(イベント2)の処理または結果を違ったものにしたい場合はどうなのでしょう?
> イベント1の結果でイベント2が変化するのなら、その結果をイベント2内でIFなりSelect Caseで分岐させればよいのだと思いますが、イベント1の結果ではなく発生したかしていないかで分岐や追加処理の付加などをしたい場合、どのようにしたら良いのでしょう?可能でしょうか? 

イベントが発生したこと自体を結果と見なせば,同じ事です。
Private _event1Raised As Boolean = False

Private Sub Event1 (sender As Object, e As EventArgs)
    _event1Raised = True
End Sub

Private Sub Event2 (sender As Object, e As EventArgs)
    If _event1Raised Then
        ' Event1 発生済み 
    Else
        ' Event1 未発生 
    End If
End Sub

単純に,時間のかからない問題であれば,イベントハンドラにそのまま記述することができます。