メインスレッド以外でWPFを利用する

WPFのWindowをmain関数内で表示する場合は、下記のような書き方になる。

[<STAThread>]
[<EntryPoint>]
let main argv = 
    Application().Run(Window()) |> ignore


別スレッドでWindowを表示したい場合は下記のようになる。

let startApp() =
    Application().Run(Window()) |> ignore
let thread = Thread(startApp)
thread.SetApartmentState(ApartmentState.STA)
thread.Start()


ただしApplicationインスタンスはAppDomainに対し一つしか生成できないため、上記のスレッドを二つ以上走らせるとエラーとなる。

ちなみにApplicationインスタンスを生成しない場合(WPFのコントロールクラスの利用のみなど)スレッドを複数生成できるが、WPFのコントロールを生成(DispatcherObjectを継承したクラスの生成)した際にDispatcherが生成されるため、自前で開放する必要がある。

let noApplication() =
    let button = Button()
    Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.SystemIdle)
    Dispatcher.Run()    
let thread = Thread(noApplication)
thread.SetApartmentState(ApartmentState.STA)
thread.Start()