在onconnect例程中调用winform时出错

时间:2015-03-16 11:14:37

标签: .net vb.net multithreading winforms sockets

我设计了一个异步套接字客户端,在连接之后我唤起了这个OnConnect例程。

目标是将主窗口中的状态文本设置为“已连接”,然后向用户显示登录对话框

Friend Sub OnConnect(ByVal ar As IAsyncResult)
        Try
            oSocket.EndConnect(ar)
            MainDialog.SetStatus("Connected") <-- this line is giving the error

            'We are connected so start listening for messages
            byteData = New Byte(1023) {}
            'Start listening to the data asynchronously
            oSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, New AsyncCallback(AddressOf OnReceive), Nothing)
            '// show login dialog
            loginDlg = New LoginDialog
            loginDlg.ShowDialog()
        Catch ex As Exception
            ShowMessage(String.Format(My.Resources.error_failed_reason, "connect", "server", ex.Message), MessageBoxIcon.Information)
        End Try
    End Sub

但我得到了一个例外

  

创建表单时出错。请参阅Exception.InnerException   细节。错误是:当前线程必须设置为单线程   在进行OLE调用之前的公寓(STA)模式。确保你的   主函数上标有STAThreadAttribute。

我没有使用任何线程,只是异步套接字

可能导致此错误的原因是什么? 是在另一个线程中调用的OnConnect吗?

修改

我刚刚添加了这个

我的应用程序单线程
Public Class Program
    <STAThread()> _
    Shared Sub Main()
        Dim frm As New MainDialog
        Application.Run(frm)
    End Sub
End Class

编辑2

我替换了这一行

MainDialog.SetStatus("Connected")

使用此行

If MainDialog.InvokeRequired Then  <-- This line gives the same error as above
    MainDialog.Invoke(New LoginDelegate(AddressOf ShowLogin), "Connected")
End If

我在上面的模块中创建了这个委托

Private Delegate Sub LoginDelegate(ByVal Item As Object)

3 个答案:

答案 0 :(得分:2)

您不应更新工作线程中的UI。在工作线程中,MainDialog.SetStatusloginDlg.ShowDialog都不是有效的事情。

理想情况下,您应该在UI线程中调用它。您可以致电Control.InvokeControl.BeginInvoke来完成此操作。

参考How to update the GUI from another thread in C#?

答案 1 :(得分:0)

您需要使用STAThread属性(阅读更多here)。请注意,您使用主线程 。如果您没有使用某个帖子,则无法运行您的程序。

答案 2 :(得分:0)

我能够自己解决我的问题,我所做的是将代码移动到MainDialog表单。

似乎maindialog.invoke无法从其他线程调用其他线程