F#异步显示WPF窗口

Ed *_*ers 5 wpf f#

这个问题让我很生气.这是一般要点:

我在解决方案中有两个项目:第一个是F#控制台应用程序,第二个是带有DisplayWindow从WPF窗口继承的C#+ XAML类的C#库.DisplayWindow有一种方法public void SetMessage(string s) {...}可以让窗口以大闪亮的字母显示传递给它的文本,这些字母可能也会闪烁并旋转,并完成WPF擅长的所有其他操作.

问题是:从我的F#程序中我需要创建一个函数,let openAWindow text = ???以便DisplayWindow每次用文本调用它时都会异步打开一个新函数.做这个的最好方式是什么?使用async {}System.Threading.Thread?谢谢您的帮助 :)

编辑:我发现这篇博客文章http://deanchalk.com/2010/10/08/f-interacting-with-wpf-dispatcher-via-f-interactive-window/有效,但有时(?)会导致ArgumentException错误文本"已存在具有相同密钥的条目".所以我不知道那里发生了什么:(

Jon*_*rop 8

我为我们的F#for Visualization库做了这个,然后描述了我在Visual F#2010 for Technical Computing一书中使用的技术.

首先,我写了一个懒惰的thunk,Application在强制评估时初始化WPF(包括STA UI线程和):

> let ui =
    let mk() =
      let wh = new ManualResetEvent(false)
      let application = ref null
      let start() =
        let app = Application()
        application := app
        ignore(wh.Set())
        app.Run() |> ignore
    let thread = Thread start
    thread.IsBackground <- true
    thread.SetApartmentState ApartmentState.STA
    thread.Start()
    ignore(wh.WaitOne())
    !application, thread
  lazy(mk());;
val ui : Lazy<Application * Thread> = <unevaluated>
Run Code Online (Sandbox Code Playgroud)

然后我编写了一个spawn函数,将函数的应用程序分派f给一个参数x,使其在UI线程上运行:

> let spawn : ('a -> 'b) -> 'a -> 'b =
    fun f x ->
      let app, thread = ui.Force()
      let f _ =
        try
          let f_x = f x
          fun () -> f_x
        with e ->
          fun () -> raise e
      let t = app.Dispatcher.Invoke(DispatcherPriority.Send, System.Func<_, _>(f), null)
      (t :?> unit -> 'b)();;
val spawn : ('a -> 'b) -> 'a -> 'b
Run Code Online (Sandbox Code Playgroud)

现在只是openAWindow在UI线程上调用函数的情况:

let openAWindow text =
  DisplayWindow().SetMessage text

spawn openAWindow text
Run Code Online (Sandbox Code Playgroud)