In general a class should not get involved with UI implementation details. It may well be used in a scenario where it doesn't matter that the event is raised on another thread. In which case you certainly don't want to marshal. Nor would you know what to marshal to.
There's an excellent way to de-couple that in Winforms through the ISynchronizeInvoke interface, the FileSystemWatcher.SynchronizingObject is a good example of that. That property permits an application to choose whether to take care of the marshaling itself or to leave it up to FSW to do it. You make that look like this in an example class with a Foo event (VS2010 syntax):
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
A Form class can now simply assign itself to the SynchronizingObject property, like this:
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