【问题标题】:error while invoking winform in onconnect routine在 onconnect 例程中调用 winform 时出错
【发布时间】:2015-03-16 11:14:37
【问题描述】:

我设计了一个异步套接字客户端,连接后我调用了这个 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)

【问题讨论】:

  • 您在哪一行得到异常?
  • 在这一行MainDialog.SetStatus("Connected") &lt;-- this line is giving the error
  • 我现在重新阅读了这个问题,一开始我错过了:)。您只需要像 Lajos 建议的那样设置 STAThread 属性,它应该可以正常工作。告诉我们它是否不能解决问题。可能是该事件是从另一个线程触发的,在这种情况下您需要一个差异。解决方案。
  • 检查InnerException 属性以查看它的内容。您更新的代码不应抛出此异常 AFAICT。如果你准备一个short but complete sample 来演示这个问题,将会很有帮助。
  • 错误是一样的

标签: .net vb.net multithreading winforms sockets


【解决方案1】:

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

理想情况下,您应该在 UI 线程中调用它。您可以通过调用Control.InvokeControl.BeginInvoke 来完成。

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

【讨论】:

  • @Smith 没关系。异步 I/O 回调将在工作线程中调用。它将在 IO 完成线程中调用。您需要通过 Control.Invoke 或 Control.BeginInvoke 将控件传递给 UI 线程
  • @Smith 似乎该事件是从另一个线程触发的——即使它 STA,由于缺少BeginInvoke,您仍然会得到一个跨线程操作异常.
  • 我已经用这个If MainDialog.InvokeRequired Then MainDialog.Invoke(New LoginDelegate(AddressOf ShowLogin), "Connected") End If 替换了MainDialog.SetStatus("Connected"),但我仍然收到错误
  • @Smith 您现在在哪一行得到错误,相同或不同的错误是什么?在哪一行?发布更新的代码,以便我们可以看到您做错了什么。
【解决方案2】:

您需要使用STAThread 属性(阅读更多here)。请注意,您正在使用一个线程,即您的主线程。如果您不使用线程,您将无法运行您的程序。

【讨论】:

  • 问题是否仍然存在?
【解决方案3】:

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

似乎 maindialog.invoke 不能从 UI 线程以外的另一个线程调用

【讨论】:

    猜你喜欢
    • 2018-02-22
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    相关资源
    最近更新 更多