使所有类事件在与构造函数调用线程相同的线程上触发

时间:2013-02-23 01:41:37

标签: c# .net vb.net multithreading invoke

我有一个Windows窗体应用程序和一个类。

该类在不同的线程中触发事件,因此我需要在接收事件的表单中的函数中执行Control.InvokeRequiredControl.Invoke()的代码。

是否可以在类上进行所有线程处理,这样我就不需要在表单中执行Invoke(),并假设所有即将发生的事件已经在同一个线程上?

我正在考虑的解决方案,我不喜欢,是在类的构造函数中启动虚拟控件,或者传递对类中表单的引用,并检查InvokeRequired

还有其他可能的解决方案吗?

1 个答案:

答案 0 :(得分:1)

通常,类不应该涉及UI实现细节。它可能适用于在另一个线程上引发事件无关紧要的场景。在这种情况下,你当然不想编组。你也不知道要组织什么。

有一种很好的方法可以通过ISynchronizeInvoke接口在Winforms中解耦,FileSystemWatcher.SynchronizingObject就是一个很好的例子。该属性允许应用程序选择是否自己处理编组或将其留给FSW来执行此操作。您可以在具有Foo事件(VS2010语法)的示例类中看起来像这样:

Imports System.ComponentModel

Public Class Example
    Public Event Foo As EventHandler

    Public Property SynchronizingObject As ISynchronizeInvoke

    Protected Sub OnFoo(e As EventArgs)
        If SynchronizingObject IsNot Nothing AndAlso SynchronizingObject.InvokeRequired Then
            SynchronizingObject.BeginInvoke(Sub() RaiseEvent Foo(Me, e), Nothing)
        Else
            RaiseEvent Foo(Me, e)
        End If
    End Sub
End Class

Form类现在可以简单地将自己分配给SynchronizingObject属性,如下所示:

Public Class Form1
    Private WithEvents obj As Example

    Public Sub New()
        InitializeComponent()
        obj.SynchronizingObject = Me
    End Sub

    Private Sub obj_Foo(sender As Object, e As EventArgs) Handles obj.Foo
        '' No marshaling required
        ''...
    End Sub
End Class