Vb.net Form.show()没有响应

Vb.net Form.show()没有响应,vb.net,Vb.net,我正在写一个小的POSIT程序,它应该能够让用户使用数据库向其他计算机发送小的注释。 我有一个主窗体,我可以在其中编写消息并在线查看用户,一个应该显示消息的工作表窗体和一个sql数据库,该数据库有一个用于用户和消息的表 我的想法是将消息写入Messagestable,我的程序使用它来获取新消息并在表单中显示它们。到目前为止还不错 问题是,当我向表中添加一条新消息时,SqlDependency会触发一个事件,而我的mainForm会创建一个新的工作表,该工作表会在调用sheet.Show后冻结。主

我正在写一个小的POSIT程序,它应该能够让用户使用数据库向其他计算机发送小的注释。 我有一个主窗体,我可以在其中编写消息并在线查看用户,一个应该显示消息的工作表窗体和一个sql数据库,该数据库有一个用于用户和消息的表

我的想法是将消息写入Messagestable,我的程序使用它来获取新消息并在表单中显示它们。到目前为止还不错

问题是,当我向表中添加一条新消息时,SqlDependency会触发一个事件,而我的mainForm会创建一个新的工作表,该工作表会在调用sheet.Show后冻结。主窗体继续运行,但我的工作表始终没有响应

这是我的密码: DBListener:

 Imports System.Data
    Imports System.Data.Sql
    Imports System.Data.SqlClient
    Imports System.Threading

Public Class DBListener

    Private changeCount As Integer = 0

    Private Const tableName As String = "IMSMessages"
    Private Const statusMessage As String = _
       "{0} changes have occurred."
    Private exitRequested As Boolean = False
    Private waitInProgress As Boolean = False
    Private recieverHost As String
    Private imsMain As IMSMain

    Public Sub New(main As IMSMain, recieverHost As String)
        Me.imsMain = main
        Me.recieverHost = recieverHost
        initCommand(recieverHost)
        SqlDependency.Start(connectionString)
        GetMsg(recieverHost)
    End Sub


    Private connectionString As String = "Data Source=NB_RANDY\SQLEXPRESS;Initial Catalog=eurom_test;Integrated Security=SSPI;"
    Private sqlConn As SqlConnection = New SqlConnection(connectionString)
    Private commandMesg As SqlCommand = Nothing
    Private commandUsers As SqlCommand = Nothing

    Private Sub initCommand(recieverHost As String)
        commandMesg = New SqlCommand
        commandMesg.CommandText = "SELECT MessageID,SenderHost,RecieverHost,isRead,isRecieved,Stamp from dbo.IMSMessages " &
                                       "WHERE RecieverHost=@RecieverHost" &
                                       " AND isRecieved = 0"
        commandMesg.Parameters.Add("@RecieverHost", SqlDbType.VarChar).Value = recieverHost
        commandMesg.Connection = sqlConn

        commandUsers = New SqlCommand
        commandUsers.CommandText = "Select HostName From dbo.IMSUser"
    End Sub




    Private Sub OnChangeMsg(ByVal sender As System.Object, ByVal e As System.Data.SqlClient.SqlNotificationEventArgs)
        Dim dep As SqlDependency = DirectCast(sender, SqlDependency)
        RemoveHandler dep.OnChange, AddressOf OnChangeMsg
        GetMsg(recieverHost)
    End Sub
    Private Sub OnChangeUser(ByVal sender As System.Object, ByVal e As System.Data.SqlClient.SqlNotificationEventArgs)
        Dim dep As SqlDependency = DirectCast(sender, SqlDependency)
        RemoveHandler dep.OnChange, AddressOf OnChangeUser
        GetUsers()
    End Sub

    Public Sub GetMsg(recieverHost As String)
        If Not sqlConn.State = ConnectionState.Open Then
            sqlConn.Open()

        End If

        commandMesg.Notification = Nothing
        Dim dep As SqlDependency = New SqlDependency(commandMesg)
        AddHandler dep.OnChange, New OnChangeEventHandler(AddressOf OnChangeMsg)
        Dim table As DataTable = New DataTable
        Dim adapter As SqlDataAdapter = New SqlDataAdapter(commandMesg)
        adapter.Fill(table)
        imsMain.recieveNewMessages(table)
    End Sub
    Public Sub GetUsers()
        If Not sqlConn.State = ConnectionState.Open Then
            sqlConn.Open()

        End If

        commandMesg.Notification = Nothing
        Dim dep As SqlDependency = New SqlDependency(commandUsers)
        AddHandler dep.OnChange, New OnChangeEventHandler(AddressOf OnChangeUser)
        Dim table As DataTable = New DataTable   
        imsMain.updateOnlineUserList()
    End Sub


End Class
主要形式:

 Imports System.Data.SqlClient
    Imports System.Threading

    Public Class IMSMain

    Private user As IMSUser
    Private listener As DBListener


    Private sqlConn As SqlConnection

    Public Sub New()
        InitializeComponent()
        sqlConn = New SqlConnection("Data Source=NB_RANDY\SQLEXPRESS;Initial Catalog=eurom_test;Integrated Security=SSPI;")



        Me.user = New IMSUser(My.Computer.Name)
        user.register()

        updateOnlineUserList()
        listener = New DBListener(Me, user.HostName)

    End Sub
    Private Sub onSend(sender As Object, e As EventArgs) Handles bt_send.Click
        Dim command As SqlCommand = New SqlCommand
        Dim msgText = tb_text.Text
        Dim reciever As IMSUser = lb_Online.SelectedItem
        Dim insert_string As String = "Insert INTO dbo.IMSMessages(Text,RecieverHost,SenderHost,isRead,isRecieved,Stamp) Values(@Text,@RecieverHost,@SenderHost,@isRead,@isRecieved,@Stamp)"
        Dim adapter As SqlDataAdapter = New SqlDataAdapter
        Dim table As DataTable = New DataTable()
        Try

            If Not sqlConn.State = ConnectionState.Open Then
                sqlConn.Open()

            End If
            command.Connection = sqlConn
            command.CommandText = insert_string
            adapter.SelectCommand = command
            adapter.Fill(table)
            command.CommandText = insert_string
            command.Parameters.Add("@Text", SqlDbType.VarChar).Value = msgText
            command.Parameters.Add("@RecieverHost", SqlDbType.NChar).Value = reciever.HostName
            command.Parameters.Add("@SenderHost", SqlDbType.NChar).Value = user.HostName
            command.Parameters.Add("@isRecieved", SqlDbType.Bit).Value = 0
            command.Parameters.Add("@isRead", SqlDbType.Bit).Value = 0
            command.Parameters.Add("@Stamp", SqlDbType.SmallDateTime).Value = DateTime.Now
            command.ExecuteNonQuery()
        Catch ex As Exception
            Console.WriteLine("onSend: internal database exception" + ex.Message)
        End Try
    End Sub

    Private Sub processMessageId(refMessageID As Integer)
        Dim command As SqlCommand = New SqlCommand
        Dim msgID_string As String = "SELECT * from dbo.IMSMessages " &
                                       "WHERE MessageID=@MessageID AND isRecieved = 0" &
                                       " ORDER BY Stamp"
        Dim isRecievedUpdate_string As String = "Update dbo.IMSMessages " &
                                            "SET isRecieved=1" &
                                             " WHERE MessageID=@MessageID"
        Dim adapter As SqlDataAdapter = New SqlDataAdapter
        Dim table As DataTable = New DataTable()
        Try
            If Not sqlConn.State = ConnectionState.Open Then
                sqlConn.Open()

            End If
            command = New SqlCommand
            command.CommandText = msgID_string
            command.Parameters.Add("@MessageID", SqlDbType.Int).Value = refMessageID
            command.Connection = sqlConn
            adapter.SelectCommand = command
            adapter.Fill(table)
            command = New SqlCommand
            command.Connection = sqlConn
            command.CommandText = isRecievedUpdate_string
            command.Parameters.Add("@MessageID", SqlDbType.Int).Value = refMessageID
            command.ExecuteNonQuery()

        Catch ex As Exception
            Console.WriteLine("processMessageID: internal database exception" + ex.Message)
        End Try
        Try
            Dim row As DataRow = table.Rows(0)
            Dim senderHost As String = row("SenderHost")
            Dim sender As IMSUser = New IMSUser(senderHost)
            Dim currentSheet As IMSSheet
            Dim stringText As String = row("Text")
            Dim stamp As Date = row("Stamp")
            currentSheet = New IMSSheet(sender, stringText, stamp)
            currentSheet.Show()
        Catch ex As Exception
            Console.WriteLine("processMessageID: error while showing sheet")
        End Try
    End Sub

    Public Sub recieveNewMessages(newMessageTable As DataTable)
        For Each row As DataRow In newMessageTable.Rows
            Dim id As Integer = row("MessageID")
            processMessageId(id)
        Next
    End Sub

    Public Sub updateOnlineUserList()
        lb_Online.Items.Clear()
        Dim adapter As SqlDataAdapter = New SqlDataAdapter
        Dim table As DataTable = New DataTable()
        Dim command As SqlCommand = New SqlCommand
        Dim onlineUser_string = "Select * FROM dbo.IMSUser"
        command.CommandText = onlineUser_string
        Try
            If Not sqlConn.State = ConnectionState.Open Then
                sqlConn.Open()

            End If
            command.Connection = sqlConn
            adapter.SelectCommand = command
            adapter.Fill(table)
        Catch ex As Exception
            Console.WriteLine("internal database exception" + ex.Message)
        End Try
        For Each row As DataRow In table.Rows

            Dim tmp As IMSUser = New IMSUser(row("HostName"))
            If Not user.Equals(tmp) Then
                lb_Online.Items.Add(tmp)
            End If
        Next
    End Sub

End Class
表格:

    Public Class IMSSheet
        Dim IsDraggingForm As Boolean = False
        Private MousePos As New System.Drawing.Point(0, 0)

    Public Sub New(session As IMSUser, text As String, stamp As Date)
        Ini

tializeComponent()
            Me.tb_sender.Text = session.HostName
            addText(text, stamp)
        End Sub

        Private Sub addText(msg As String, stamp As DateTime)
            Dim currentText As String = tb_text.Text
            currentText = currentText + stamp.ToString + Environment.NewLine + msg + Environment.NewLine
            tb_text.Text = currentText
        End Sub
        Private Sub IMSSheet_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseDown
            If e.Button = MouseButtons.Left Then
                IsDraggingForm = True
                MousePos = e.Location
            End If
        End Sub

        Private Sub IMSSheet_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseUp
            If e.Button = MouseButtons.Left Then IsDraggingForm = False
        End Sub

        Private Sub IMSSheet_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseMove
            If IsDraggingForm Then
                Dim temp As Point = New Point(Me.Location + (e.Location - MousePos))
                Me.Location = temp
                temp = Nothing
            End If
        End Sub

        Private Sub onClose(sender As Object, e As EventArgs) Handles bt_Close.Click
            Me.Close()
        End Sub


        Private Sub bt_minimize_Click(sender As Object, e As EventArgs) Handles bt_minimize.Click
            Me.WindowState = FormWindowState.Minimized
        End Sub

        Private Sub bt_Close_MouseHover(sender As Object, e As EventArgs) Handles bt_Close.MouseHover

        End Sub

        Private Sub bt_minimize_MouseHover(sender As Object, e As EventArgs) Handles bt_minimize.MouseHover

        End Sub
    End Class
有趣的是,如果在运行程序之前,我的Messagestable中已经有一些新消息,它们将正确显示。 如果我使用Form.ShowDialog显示图纸,它也可以工作,但不是我想要的工作方式


由于我没有主意,希望您能帮助我。

您遇到了问题,因为SqlDependency的更改事件发生在您的UI线程所在的另一个线程上。从:

OnChange事件可能在与 启动命令执行的线程


在非UI线程上调用sheet.Show时,Show将锁定,因为没有消息循环来处理UI事件。在ImsMain上使用可在UI线程上创建和显示ImsSheet。

在show调用上设置断点。当它中断时,使用Debug+Windows+Threads查看代码在哪个线程上运行。很有可能您会发现它不在程序的主UI线程上。这会让身体像门钉一样死掉。您需要使用Control.BeginInvoke使代码在UI线程上运行,而窗体有可能在该线程上运行。您的Catch块是否会捕获一个异常,而您无法看到,因为您正在使用Console.Writeline和窗体应用程序?尝试改用MessageBox.Showex.Message。谢谢。。我要试试你说的@Tinstaaff我已经尝试捕捉任何异常,但没有任何异常。。。你是对的,我现在使用的是调试而不是控制台。我必须尝试一下,但似乎这可能是问题所在。