なぜ、C#、VB.NETでは別スレッドからはControl.Invokeを使わないとフォームの表示が更新できないのか?

https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls
別スレッドからフォームを更新するには、以下のようにInvokeを使ったコードを書かないとエラーになる。

Me.Text = "task start"
Task.Run(Sub()
             System.Threading.Thread.Sleep(3000)

             ' Me.Text = "task end"                ' これはエラーになる
             Me.Invoke(Sub() Me.Text = "task end") ' これならOK

         End Sub)

なぜならば、フォームやコントロールの操作はスレッドセーフではないからである。つまりフォームは別スレッドから変化させられることを考慮していないため、別スレッドから更新されるとデッドロックや正しくない更新が発生する可能性がある。
.NET Framework は実際にデッドロックや正しくない更新が起きないように、別スレッドからフォームやコントロールの操作を行おうとしたとき自動的に InvalidOperationException を発生させる。
それを回避するためには、コントロールの基になるウィンドウハンドルを所有するスレッド上で操作を行うよう指示をしてやる必要がある。
この「コントロールの基になるウィンドウハンドルを所有するスレッド上で操作を行え」という命令がControl.Invokeメソッドである。



ちなみに、リフレクション(文字列でメソッド名を指定して実行したり、privateメソッドを指定した実行したり)でも、MethodInfo.InvokeやType.InvokeMemberを使うが、これはたまたま名前が同じだけであり、スレッドとは関係ない。