线程安全访问来自F#的Windows窗体控件

时间:2011-01-08 19:15:14

标签: f# windows-phone-7

我正在尝试使用以下F#代码来访问Xaml控件。

let (?) (source:obj) (s:string) =
    match source with 
    | :? ResourceDictionary as r ->  r.[s] :?> 'T
    | :? Control as source -> 
        match source.FindName(s) with 
        | null -> invalidOp (sprintf "dynamic lookup of Xaml component %s failed" s)
        | :? 'T as x -> x
        | _ -> invalidOp (sprintf "dynamic lookup of Xaml component %s failed because the component found was of type %A instead of type %A"  s (s.GetType()) typeof<'T>)
    | _ -> invalidOp (sprintf "dynamic lookup of Xaml component %s failed because the source object was of type %A. It must be a control or a resource dictionary" s (source.GetType()))

这是来自Daniel Mohl的优秀F#for Windows Phone模板。

我创建了一个基本上读取加速度计的类,并在手机动摇时触发事件。事件按预期引发但由于某种原因它在第二个线程中生成 - 当事件处理程序尝试执行此代码时,它会导致CLR抛出“无效的跨线程访问”异常。 source.FindName(s)电话会抛出异常。我可以看到第二个执行线程 - 这让我感到惊讶,因为我没有专门产生一个辅助线程。我的意思是我没有明确地调用异步或做任何我能想到的事情会导致第二个执行线程启动。

所以似乎我可以采取一些方法:

  1. 我可以试着找出我为什么 我生成一个辅助线程 没有具体请求它并修改代码以防止二级线程 从产生的执行。
  2. 我可以尝试修改(?) 功能来考虑多个 执行的线索,但我真的 想明白为什么我会得到一个 第二个线程开始
  3. 我认为第二种方法可能是最好的,但我真的很想了解我正在做的事情导致一个辅助线程产生。我意识到如果没有具体的代码,回答有多难,但如果有人能指出我正确的方向,我不介意研究这个问题。我认为这与Windows 7 Phone平台有关,因为就我所知,代码几乎是将Xaml控件与F#代码绑定的惯用方法。

    任何想法,评论和建议都将不胜感激。

    交叉发布到HubFS

1 个答案:

答案 0 :(得分:3)

WP7中的事件处理通常在异步回调上处理。访问加速度计也不例外。

您需要将导致UI更新的任何代码定向到调度程序。

在c#中,这可以像

那样完成
Dispatcher.BeginInvoke( () => { /* your UI code */ } );

将结果发送到本文中使用的Dispatcher的方法在f#中也可能对你有所帮助,因为它更像是一种功能风格,而不是使用Rx的命令。

WP7 Code: Using the Accelerometer API - Dragos Manolescu's (work) blog