Imports Mercury.Mobile.Threading
Imports System.Windows.Forms
Imports System.Threading
Imports System.ComponentModel

''' <summary>
''' A synchronization context for the System.Windows.Forms application model.
''' </summary>
''' <remarks></remarks>
Public Class WinFormsSynchronizationContext
    Inherits ThreadSynchronizationContext
    Implements IDisposable

    ''' <summary>
    ''' Initializes a new instance of the <see cref="Mercury.Mobile.Forms.WinFormsSynchronizationContext"/> 
    ''' class with the specified marshalling control.
    ''' </summary>
    ''' <param name="marshallingControl"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal marshallingControl As Control)
        Me.DestinationThread = Thread.CurrentThread
        Me.marshaller = marshallingControl
    End Sub

    Private Sub New(ByVal marshallingControl As Control, ByVal destinationThread As Thread)
        Me.marshaller = marshallingControl
        Me.DestinationThread = destinationThread
    End Sub

    Private marshaller As Control
    Private m_destinationRef As WeakReference
    Private disposedValue As Boolean = False

    Private Property DestinationThread() As Thread
        Get
            If Me.m_destinationRef IsNot Nothing AndAlso Me.m_destinationRef.IsAlive Then _
                Return TryCast(Me.m_destinationRef.Target, Thread)
            Return Nothing
        End Get
        Set(ByVal value As Thread)
            If value IsNot Nothing Then _
                Me.m_destinationRef = New WeakReference(value)
        End Set
    End Property

    Public Overrides Sub Post(ByVal d As ContextSendOrPostCallback, ByVal state As Object)
        If Me.marshaller IsNot Nothing Then
            Me.marshaller.BeginInvoke(d, New Object() {state})
        End If
    End Sub

    Public Overrides Sub Send(ByVal d As ContextSendOrPostCallback, ByVal state As Object)
        Dim dest = Me.DestinationThread
        If dest Is Nothing OrElse Not (Me.m_destinationRef.IsAlive) Then _
            Throw New InvalidOperationException("The thread is no longer valid.")
        If Me.marshaller IsNot Nothing Then
            Me.marshaller.Invoke(d, New Object() {state})
        End If
    End Sub

    Public Function CreateCopy() As ThreadSynchronizationContext
        Return New WinFormsSynchronizationContext(Me.marshaller, Me.DestinationThread)
    End Function

#Region "IDisposable"
    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If Me.marshaller IsNot Nothing Then _
                Me.marshaller.Dispose()
            Me.marshaller = Nothing
        End If
        Me.disposedValue = True
    End Sub
#End Region

End Class