私は小さなデータベース管理ツールを開発しています。アプリケーションを起動してデータベースに接続しようとしましたが、データベースがネットワークドライブに常駐しているので、時間がかかることがあります。この間、アプリケーションはハングアップします。VB.Net別のスレッドでタスクを実行する
次のコードを使用して、別のスレッドでデータベースに接続するコードを実行して、アプリケーションをロードしてデータベースを別々に接続できるようにしています。上記と
Public Class Incident_Form
'DELEGATE CLASSES
Delegate Sub UpdateTable()
'DELEGATE VARIABLES
Public UpdateTableVar As UpdateTable
Private Sub Incident_Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
I_List.DataSource = Nothing
Display_Module.Maximise_Window()
Splash_Panel.BringToFront()
System.Windows.Forms.Application.DoEvents()
UpdateTableVar = New UpdateTable(AddressOf Me.UpdateTableHandler)
Me.Invoke(Me.UpdateTableVar)
End Sub
Public Sub UpdateTableHandler() 'Handles the background work for updating I_LIST
If (Me.InvokeRequired) Then
Me.Invoke(UpdateTableVar)
Else
Dim myCon = New OleDbConnection(My.Settings.Database_Connection_String)
myCon.Open()
Dim ds As DataSet = New DataSet
Dim adapter As New OleDb.OleDbDataAdapter
Dim sql As String
sql = "SELECT [IN_REF], [Incident Name], [Date Created], [Created By] " & _
"FROM [Master_Record]"
adapter.SelectCommand = New OleDb.OleDbCommand(sql, myCon)
adapter.Fill(ds)
I_List.DataSource = ds.Tables(0)
I_List.Columns(1).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
I_List.Columns(0).HeaderText = "Reference"
I_List.Sort(I_List.Columns("Date Created"), System.ComponentModel.ListSortDirection.Descending)
myCon.Close()
End If
End Sub
問題は、アプリケーションがロードされ、正しくフォームを表示しているが、データベースが接続完了するまで、ユーザは依然としてフォームと相互作用しないことです。それは別のスレッドで実行されているようですが、そのスレッドが終了するまで待ってから続行されます。
私には何かがありませんか、これは正しい方法ではありませんか?
UPDATE 1
助けのおかげで、私は次のようにコードを更新したし、すべてが正しく動作している:)
Public Class Incident_Form
Dim ds As DataSet = New DataSet
Private Sub Incident_Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
I_List.DataSource = Nothing
Display_Module.Maximise_Window()
Splash_Panel.BringToFront()
System.Windows.Forms.Application.DoEvents()
Try
BackgroundWorker1.RunWorkerAsync()
Catch ex As Exception
BackgroundWorker1.WorkerSupportsCancellation = True
BackgroundWorker1.CancelAsync()
End Try
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
UpdateTableHandler()
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
I_List.DataSource = ds.Tables(0)
I_List.Columns(1).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
I_List.Columns(0).HeaderText = "Reference"
I_List.Sort(I_List.Columns("Date Created"), System.ComponentModel.ListSortDirection.Descending)
End Sub
Public Sub UpdateTableHandler() 'Handles the background work for updating I_LIST
Dim myCon = New OleDbConnection(My.Settings.Database_Connection_String)
myCon.Open()
Dim adapter As New OleDb.OleDbDataAdapter
Dim sql As String
sql = "SELECT [IN_REF], [Incident Name], [Date Created], [Created By] " & _
"FROM [Master_Record]"
adapter.SelectCommand = New OleDb.OleDbCommand(sql, myCon)
adapter.Fill(ds)
myCon.Close()
End Sub
ここではマルチスレッド化はありません。セカンダリスレッドでコードを実行する方法はいくつかあります。そこにWinFormsを使用しているので、論理的なオプションは 'BackgroundWorker'を使用するようです。 'DoWork'イベントハンドラでバックグラウンドを処理し、' RunWorkerCompleted'イベントで必要ならUIを更新します。 – jmcilhinney
ええ、マルチスレッド化はまったくありません。 - 「デリゲートクラス」*とはどういう意味ですか?そのようなことはありません、クラスはデリゲートすることはできませんが、**インスタンス**できます。あなたの例では、基本的にメインのUIスレッドから特定のUIコントロールスレッドに作業を移行しています。これにより、UI全体ではなく、このコントロールがハングします。それは "ダメージコントロール"と呼ばれています:-)。 データが届いたら**あなたのコントロールを更新する**実際のスレッドを導入してください**あなたは行こうとしていますが、まだ読み込み中でも編集機能を無効にする必要があります。 – specializt
ありがとう@specializt、バックグラウンドワーカーでデータセットを読み込んだ後にコントロールを更新すると、懸垂の問題が修正されました – SilverShotBee