【问题标题】:How to tell if Invoke is required for a property?如何判断属性是否需要调用?
【发布时间】:2009-02-11 19:00:31
【问题描述】:

如果我从非 UI 线程设置窗体的 Text 属性,那么我需要使用 Invoke 来避免跨线程错误。但是,我可以在不使用 Invoke 的情况下读取 Text 属性。这安全吗?如果我尝试读取 Form 的 Handle 属性,则会出现跨线程错误。如果我阅读 Form 的 IsDisposed 属性,它可以正常工作。如何判断何时需要使用 Invoke?我是否应该始终使用 Invoke 来读取和写入属性值?

【问题讨论】:

    标签: c# multithreading invoke


    【解决方案1】:

    当您处于 UI 线程以外的线程中时,您应该在访问 UI 对象时使用Invoke。使用InvokeRequired 属性来确定您是否确实在另一个线程中。

    【讨论】:

    • +1,您要查找的方法(或属性?)是调用所需的
    • 所以我应该对所有属性使用 Invoke,即使是那些没有它也能工作的属性(比如 IsDisposed)?
    • 我正在使用 InvokeRequired 来访问 Text 属性,例如,我想我的问题更多的是我是否需要始终使用 Invoke,或者仅针对通过“跨线程”的属性"异常?
    • 始终使用 Invoke(或 BeginInvoke)。仅仅因为一个属性碰巧没有抛出异常并不意味着它是安全的。 InvokeRequired 的文档解释了在“错误”线程上做什么是安全的。
    • 谢谢乔恩。它似乎总是有点命中或错过,所以我倾向于使用 Invoke 来处理几乎所有事情。我将更新我的代码以始终使用 Invoke。
    【解决方案2】:

    最简单的方法是使用:

    Delegate Sub SetTextCallback(ByVal [text] As String)
    
    Private Sub SetText(ByVal [text] As String)
    ' InvokeRequired required compares the thread ID of the
    ' calling thread to the thread ID of the creating thread.
    ' If these threads are different, it returns true.
    If Me.lboxResults.InvokeRequired Then
        Dim d As New SetTextCallback(AddressOf SetText)
        Me.Invoke(d, New Object() {[text]})
    Else
        Me.lboxResults.Items.Add([text])
    End If
    

    结束子

    对不起 VB 代码...

    【讨论】:

      【解决方案3】:

      另一个选择是使用 SynchronizationContext。这不仅适用于 WinForms,也适用于 WPF 和 ASP.NET,并且它从 .NET 2.0 开始可用。

      在主线程(例如在构造函数中)调用 SynchronizationContext.Current,并在需要同步调用时使用返回的对象。如果对象为空,则不需要同步。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-14
        • 1970-01-01
        • 1970-01-01
        • 2010-09-16
        • 1970-01-01
        • 2011-04-23
        • 1970-01-01
        相关资源
        最近更新 更多