<Query Kind="FSharpProgram">
  <Reference>&lt;RuntimeDirectory&gt;\System.Windows.Forms.dll</Reference>
</Query>

open System
open System.Threading 

let TID () = Thread.CurrentThread.ManagedThreadId

open System.Windows.Forms 
open System.Drawing 

let textBox = new TextBox (
                Multiline = true,
                ScrollBars = ScrollBars.Vertical,    
                Dock = DockStyle.Fill, 
                ReadOnly = true)

textBox.Font <- new Font (
                FontFamily.GenericMonospace, 
                float32 14, 
                FontStyle.Bold)
    
let flag = ref true

let button = new Button (
                Text = "Stop Asyncs!")
button.Click.AddHandler (fun o x -> Console.WriteLine ("... stop!"); flag := false)

PanelManager.DisplayControl(textBox, "AsyncGUI") |> ignore
PanelManager.DisplayControl(button, "Stop!") |> ignore

let guiContext = SynchronizationContext.Current

let task number = async {
    let rnd = new Random(number)
    while !flag do
        let th1 = TID()  // thread pool
        
        do! Async.Sleep (rnd.Next(1000, 7000)) // simulate long computation
        let th2 = TID()  // thread pool
        
        do! Async.SwitchToContext(guiContext)
        let tgui = TID()  // GUI
        
        let line = sprintf "task=%d, th1=%2d, th2=%2d, tgui=%2d" number th1 th2 tgui
        //Console.WriteLine (line)
        textBox.Text <- sprintf "%s%s\r\n" textBox.Text line
        textBox.SelectionStart <- textBox.Text.Length
        textBox.ScrollToCaret()
        
        do! Async.SwitchToThreadPool()
    
    Console.WriteLine ("task={0}, stop!", number)
} 

// ---------------------------------------
// start gui linqpad

[task 1; task 2; task 3] |> Async.Parallel |> Async.Ignore |> Async.Start         

// ---------------------------------------