1

Is the WPF event loop in this answer still a good one for FSI (besides rethrow which is now reraise)? The answer is from 2008 and I'm not sure if there are any "better" implementations around. If not what would one be?

My understanding is that the default implementation is for WinForms.

Community
  • 1
  • 1
Stephen Swensen
  • 22,107
  • 9
  • 81
  • 136

1 Answers1

2

Yes the default is for Winforms, I do use the WpfEventLoop quite a lot, Code is below,

#I "c:/Program Files/Reference Assemblies/Microsoft/Framework/v3.0"
#I "C:/WINDOWS/Microsoft.NET/Framework/v3.0/WPF/"
#r "PresentationCore.dll"
#r "PresentationFramework.dll"
#r "WindowsBase.dll"

module WPFEventLoop =     
    open System    
    open System.Windows    
    open System.Windows.Threading    
    open Microsoft.FSharp.Compiler.Interactive    
    open Microsoft.FSharp.Compiler.Interactive.Settings    

    type RunDelegate<'b> = delegate of unit -> 'b     
    let Create() =         
        let app  =             
            try                 
                // Ensure the current application exists. This may fail, if it already does.                
                let app = new Application() in                 
                // Create a dummy window to act as the main window for the application.                
                // Because we're in FSI we never want to clean this up.                
                new Window() |> ignore;                 
                app              
            with :? InvalidOperationException -> Application.Current        
        let disp = app.Dispatcher        
        let restart = ref false        
        { new IEventLoop with             
            member x.Run() =                    
                app.Run() |> ignore                 
                !restart             

            member x.Invoke(f) =                  
                try 
                    disp.Invoke(DispatcherPriority.Send,new RunDelegate<_>(fun () -> box(f ()))) |> unbox                 
                with e -> eprintf "\n\n ERROR: %O\n" e; reraise()             

            member x.ScheduleRestart() =   ()                 
            //restart := true;                 
            //app.Shutdown()        
         }     

    let Install() = fsi.EventLoop <-  Create()

WPFEventLoop.Install()

Test code

open System
open System.Windows
open System.Windows.Controls

let window = new Window(Title = "Simple Test", Width = 800., Height = 600.)
window.Show()

let textBox = new TextBox(Text = "F# is fun")
window.Content <- textBox

Let me know if this helps.

-Fahad

Gary McConnell
  • 125
  • 1
  • 4
Fahad
  • 858
  • 1
  • 8
  • 15
  • cool, and you've never had any issues using this WPF event loop (same as the one I linked to that @Robert provided, and I think used to come with F# samples pre-2.0)? I know sometimes the WinForms event loop can act strangely. And looking at this WPF implementation, some curious things are 1) `ScheduleRestart` is a no-op with some code commented out, 2) `restart` is never really used – Stephen Swensen May 11 '11 at 19:00
  • Well, I use it for quick testing with WPF, like once I checked out WPF 3D models for some container load programming. Mostly I go with MVVM pattern so I only have to test the model and provide it to the UI. – Fahad May 12 '11 at 17:31
  • Sometimes like if code tries to set `Window.DialogResult` on a window I'm poking around, I get flooded with `error FS0193: internal error: Application is already running the Dispatcher.` and the window, ui thread, and fsi just dies. – Maslow Jul 07 '16 at 17:20
  • I haven't been able to get this to work. `Run()` is never called. Does this still work in 2018? – Rei Miyasaka Apr 03 '18 at 18:55