我正在寫一個小型的postIt程序,它應該使用戶能夠使用數據庫向其他計算機發送小筆記。 我有一個主要的表單,我可以在那裏寫信息並在線查看用戶,一個應該顯示消息的表單以及一個包含用戶和消息表的sql數據庫。Form.show()不響應
這個想法是,我正在將消息寫入Messagestable,我的程序使用SqlDependency來獲取新消息並將它們顯示在工作表中。到現在爲止還挺好。
問題是,當我添加一個新的消息到我的表SqlDependency觸發一個事件和我的mainForm創建一個新的表後凍結sheet.Show()被調用後。 mainForm繼續運行,但我的工作表總是不響應。
這裏是我的代碼: 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 [email protected]" &
" 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
IMSMain表格:
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 [email protected] AND isRecieved = 0" &
" ORDER BY Stamp"
Dim isRecievedUpdate_string As String = "Update dbo.IMSMessages " &
"SET isRecieved=1" &
" WHERE [email protected]"
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
IMSSheet表格:
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中,他們將顯示cor rectly。 如果我使用Form.ShowDialog()顯示工作表,它也可以工作,但它不是我希望它工作的方式。
由於我出於主意,我希望你能幫助我。
在Show()調用上設置一個斷點。當它中斷時,使用Debug + Windows + Threads來查看代碼在哪個線程上運行。很高的可能性,你會發現它不是你的程序的主UI線程*。這使得窗體像門扇一樣死去。您需要使用Control.BeginInvoke()來讓代碼在UI線程上運行,表單有機會運行。 –
您的Catch塊是否會捕獲異常,您無法看到,因爲您正在使用Console.Writeline和表單應用程序?請改用MessageBox.Show(ex.Message)。 – tinstaafl
謝謝..我會嘗試你所提到的。 @tinstaafl我已經試圖捕捉任何異常,但沒有...你是對的我現在使用調試而不是控制檯。 – user2580785