Heres an interesting scenario that was discussed with me by one of the quants in the front-office team yesterday.
"Can I invoke a WPF Window/Control to popup from the FSI window in Visual Studio ?" - "Yes, thats easy I said"....
"and then interact with it ASYNCHRONOUSLY via F# commands in the FSI window ?" - "hmmmm, I said"
So the first bit is easy and has been done many times before with WPF and Winforms, and that is mainly to instantiate UI controls and popups from within Fsharp Interactive, and update these controls when running F# commands..... but....... you're doing your updates synchronously on the main UI thread !
What if the update your running is a long-running task, that WPF popup is going to freeze on you, and to solve it you are facing the classic issue of STA thread affinity with either WPF or Winforms.
The common solution in standard WPF/Winforms apps is to marshall messages to the UI pump via delegates, but how would that work in F# interactive ?
After a little head-scratching, I figured it out, and here is a sample of how its done below:
#light
#r "WindowsBase"
#r "PresentationCore"
#r "PresentationFramework"
open System
open System.Windows
open System.Windows.Controls
open System.Threading
open System.Windows.Threading
// create a reference to a WPF control in interactive window
let mutable (wp : TextBlock) = null
// create a new WPF gui thread with a running dispatcher and message pump
let thread = new System.Threading.Thread(fun() ->
let window = new System.Windows.Window(Name="Test",Width=500.0,Height=500.0)
wp <- new TextBlock()
wp.Text <- "test1"
window.Content <- wp
window.Visibility <- Visibility.Visible
window.Show()
window.Closed.Add(fun e ->
Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background)
Thread.CurrentThread.Abort())
Dispatcher.Run()
)
thread.SetApartmentState(ApartmentState.STA)
thread.IsBackground <- true
// start the thread, which will invoke the popup ui
thread.Start()
// once WPF window is up, you can marshall updates via its running dispatcher
wp.Dispatcher.BeginInvoke(Action(fun _ -> wp.Text <- "test2")) |> ignore
To test this, run all but the last line in the interactive window, and you should see a popup like this:

Then run the final line, which marshalls the update onto the new gui thread, and you get this

Proving the solution:
So what this means now is that we can create sophosticated WPF controls, invoke them in the FSI window, and then apply long-running upddates via FSI without the WPF window freezing on us.
That should keep the trading desk guys happy :)
Dean