2016-06-27 5 views
0

私は小さなデータベース管理ツールを開発しています。アプリケーションを起動してデータベースに接続しようとしましたが、データベースがネットワークドライブに常駐しているので、時間がかかることがあります。この間、アプリケーションはハングアップします。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 
+0

ここではマルチスレッド化はありません。セカンダリスレッドでコードを実行する方法はいくつかあります。そこにWinFormsを使用しているので、論理的なオプションは 'BackgroundWorker'を使用するようです。 'DoWork'イベントハンドラでバックグラウンドを処理し、' RunWorkerCompleted'イベントで必要ならUIを更新します。 – jmcilhinney

+1

ええ、マルチスレッド化はまったくありません。 - 「デリゲートクラス」*とはどういう意味ですか?そのようなことはありません、クラスはデリゲートすることはできませんが、**インスタンス**できます。あなたの例では、基本的にメインのUIスレッドから特定のUIコントロールスレッドに作業を移行しています。これにより、UI全体ではなく、このコントロールがハングします。それは "ダメージコントロール"と呼ばれています:-)。 データが届いたら**あなたのコントロールを更新する**実際のスレッドを導入してください**あなたは行こうとしていますが、まだ読み込み中でも編集機能を無効にする必要があります。 – specializt

+0

ありがとう@specializt、バックグラウンドワーカーでデータセットを読み込んだ後にコントロールを更新すると、懸垂の問題が修正されました – SilverShotBee

答えて

2

に追加することでBackgroundWorkerであなたのDoEvents()コールを交換してくださいあなたのフォーム。

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() 

    Try 
     BackgroundWorker1.RunWorkerAsync()  
    Catch ex As Exception 
     BackgroundWorker1p.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 
+0

これは、 'UpdateTableHandler' Subを呼び出すようには見えないので、データベースに接続していませんか? – SilverShotBee

+0

こんにちは@SilverShotBee、DoWork()サブの下でメソッドを初期化するのではなく、メソッドを直接呼び出すように答えを更新しました。ご覧のとおり、UpdateTableHandler()メソッドが呼び出されています。 – eyeshield21

+0

これはすべて動作しますが、データベースからの情報の更新中に、アプリケーションはまだハングしますか?私は何をしようとしているのか理解していますが、それでもまだぶら下がっている理由はありません – SilverShotBee

関連する問題