我正在尝试构建一个连接到几个数据库的小型应用程序,以便将数据从一个数据库移动到另一个数据库,操作和验证数据是否移动。我已经完成了所有工作,但是想将大部分工作添加到第二个线程中,以便初始窗口仍然可用。
到目前为止,我的大部分工作正常,除了一个讨厌的位。我允许用户从MSSQL Server上的数据库列表中选择数据库。如果没有线程,程序可以毫无问题地读取组合框的文本。一旦我添加了线程,它就无法读取组合框的文本。读取包含servername / username / password的文本框没有问题,只需使用这一个组合框。下面的代码位于一个处理我所有数据库函数的类中。组合框位于运行应用程序时启动的主窗体(frmMain)上。 frmMain是应用程序的默认表单。
没有线程我就是这样做的。
Me._sqlDB = New sqlDatabase
Me._sqlDB.DBServer = frmMain.txtServer.Text
Me._sqlDB.DBUsername = frmMain.txtUser.Text
Me._sqlDB.DBPassword = frmMain.txtPassword.Text
Me._sqlDB.DBDatabase = frmMain.cboSQLDatabase.Text
当我添加线程时,它无法从组合框中读取(以及由于非线程安全调用而导致的许多其他问题)。我做了一些研究,并在一些代表中添加并调用。这解决了我遇到的其他问题,但组合框仍然无法读取。
我创建了一个带委托的函数来读取组合框,希望它是一个线程相关的问题,但仍然没有运气。数据库连接设置代码在我上面提到的数据库类中,GetDatabaseName函数是主窗体(frmMain)。
'Database Connection Setup
Me._sqlDB = New sqlDatabase
Me._sqlDB.DBServer = frmMain.txtServer.Text
Me._sqlDB.DBUsername = frmMain.txtUser.Text
Me._sqlDB.DBPassword = frmMain.txtPassword.Text
Me._sqlDB.DBDatabase = frmMain.GetDatabaseName
'GetDatabaseName Function for Connection String Setup
Delegate Function GetDatabaseNameDel() As String
Public Function GetDatabaseName() As String
Dim DBName As String = ""
If Me.cboSQLDatabase.InvokeRequired Then
DBName = Me.Invoke(New GetDatabaseNameDel(AddressOf GetDatabaseName))
Else
DBName = Me.cboSQLDatabase.Text
End If
Return DBName
End Function
我尝试了几种组合框属性,包括SelectedItem,SelectedText和Text。调用GetDatabaseName函数时,它们都没有任何值。实际上,当在调试模式下运行并暂停代码执行时,Visual Studio会显示组合框中没有任何内容(Count = 0,Items集合为空)。
使用SqlDataReader填充组合框,该SqlDataReader从服务器读取数据库名称列表。
我也尝试更改设置以使用BackgroundWorker,但我得到了相同的结果。
关于为什么组合框在作为单独的线程运行时显示为空的任何想法?
通过更多的研究,我找到了一个可能的解决方案,但它看起来真的很笨拙。如果我改变对函数的调用来使用它:
Me._sqlDB.DBDatabase = CType(My.Application.OpenForms.Item("frmMain"), frmMain).GetDatabaseName
它有效,但对于这个问题,这似乎是一个非常奇怪的解决方法。有没有更好的方法来引用活动表单上的控件?