ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded apartment

后端 未结 4 2098
予麋鹿
予麋鹿 2021-01-22 20:54

I am getting this error when i try to show a form with an webbrowser in it.

ActiveX control \'8856f961-340a-11d0-a96b-00c04fd705a2\' cannot be instantiated becau

4条回答
  •  谎友^
    谎友^ (楼主)
    2021-01-22 21:29

    The problem happens because a UI component is being created on a non-UI thread. Here is a simplified version of code which will break with this error message.

    Imports System.ComponentModel
    
    Public Class Form1
        Private _ThreadedProcesss As ThreadedProcess
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            _ThreadedProcesss = New ThreadedProcess()
            _ThreadedProcesss.Start()
        End Sub
    
        Public Class ThreadedProcess
            Private _thread As System.Threading.Thread
    
            Public Sub Start()
                _thread = New System.Threading.Thread(AddressOf ThreadEntryPoint)
                _thread.Name = "Testing thread"
                _thread.Start()
            End Sub
    
            Private Sub ThreadEntryPoint(status As Object)
                Dim wb As New WebBrowser()
                wb.Dock = DockStyle.Fill
                wb.Visible = True
                wb.DocumentText = "Hello world"
            End Sub
        End Class
    End Class
    

    To correct the problem, you just need to get back to the UI thread before creating the control.

    Imports System.ComponentModel
    
    Public Class Form1
        Private _ThreadedProcesss As ThreadedProcess
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            _ThreadedProcesss = New ThreadedProcess(New EventHandler(AddressOf ThreadedProcess_Create))
            _ThreadedProcesss.Start()
        End Sub
    
        Private Sub ThreadedProcess_Create(sender As Object, e As System.EventArgs)
            If (Me.InvokeRequired) Then
                Me.Invoke(New EventHandler(AddressOf ThreadedProcess_Create), {sender, e})
            Else
                Dim wb As New WebBrowser()
                Me.Controls.Add(wb)
                wb.Dock = DockStyle.Fill
                wb.Visible = True
                wb.DocumentText = "Hello world"
            End If
        End Sub
    
        Public Class ThreadedProcess
            Private _thread As System.Threading.Thread
            Private _callback As EventHandler
    
            Public Sub New(callback As EventHandler)
                _callback = callback
            End Sub
    
            Public Sub Start()
                _thread = New System.Threading.Thread(AddressOf ThreadEntryPoint)
                _thread.Name = "Testing thread"
                _thread.Start()
            End Sub
    
            Private Sub ThreadEntryPoint(status As Object)
                _callback.Invoke(Me, EventArgs.Empty)
            End Sub
        End Class
    End Class
    

    So for your example I believe the code would be:

     Class Server
        Private _callback as EventHandler
        Public Sub Main(callback as EventHandler)
            _callback = callback
            Dim aTcpMessaging As IMessagingSystemFactory = New TcpMessagingSystemFactory()
            Dim anInputChannel As IInputChannel = aTcpMessaging.CreateInputChannel(theIPforLocal & ":" & thePort)
            Dim aStringMessagesFactory As IStringMessagesFactory = New StringMessagesFactory()
            Dim aStringMessageReceiver As IStringMessageReceiver = aStringMessagesFactory.CreateStringMessageReceiver()
            AddHandler aStringMessageReceiver.MessageReceived, AddressOf StringMessageReceived
    
            aStringMessageReceiver.AttachInputChannel(anInputChannel)
        End Sub
    
        Private Sub StringMessageReceived()
            _callback.Invoke(Me, EventArgs.Empty)
        End Sub
      End Class
    
      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
          Dim RelState As Integer = 0
          Call frmMain.Server.Main(new EventHandler(AddressOf Server_MessageReceived))   '<-- the error now
          lblVer.Text = "V.7"
          Pid = 0
      End Sub
      Private Sub Server_MessageReceived(sender as Object, e As EventArgs)
          If (Me.InvokeRequired) Then
              Me.Invoke(New EventHandler(AddressOf Server_MessageReceived), {sender, e})
          Else
              Call New frmMM().Show()
          End If
      End Sub
    End Class
    

提交回复
热议问题