3

私の Windows フォームには、約 2,000,000 行で機能するこのクエリがあります。クエリを実行するとインターフェイスがフリーズし、完了するまでに約 60 秒かかります。

タスクが進行中であることをユーザーに知らせるプログレス バーを配置する方法はありますか?

私はマルチスレッドが初めてなので、助けていただければ幸いです。

時間がかかるコードは次のとおりです。

cmd.executenonquery() でのブレークポイントのフリーズ

Public Sub InsertNumberswithMsgID(ByVal messageID As Integer, ByVal tableName As String) 

    Dim cmd As SqlCommand = Nothing

    Try
        cmd = New SqlCommand(("dbo.[InsertNumbers_withMsgID]"), cn)
        cmd.CommandType = CommandType.StoredProcedure
        cmd.Parameters.AddWithValue("@tablename", tableName)
        cmd.Parameters.AddWithValue("@msgid", messageID)
        cmd.CommandTimeout = 6000
        If Not cn Is Nothing And cn.State = ConnectionState.Closed Then cn.Open()
        cmd.ExecuteNonQuery()

    Catch ex As SqlException

    Catch ex As Exception

    Finally
        If Not cn Is Nothing And cn.State = ConnectionState.Open Then cn.Close()
        If Not cmd Is Nothing Then cmd.Dispose()
    End Try

End Function
4

2 に答える 2

1

Arman が言及した記事は、本当に良い出発点です。これをコードのスケルトンとして使用し、関数の呼び出しをスリープ コマンドのある場所に配置します。

しかし、提供した例では、ストアド プロシージャがすべてを 1 つのステップで実行し、完了すると戻るため、進行状況バーの進行状況を更新する方法は実際にはありません。

したがって、この方法では、実行前に 0% を表示し、終了後に 100% を表示します。

または、ストアド プロシージャを変更して、より細かく呼び出すことができるようにする必要があります。つまり、毎回行の 10% を処理してから戻るようにします。これにより、進行状況バーを更新できます (分割が許可されている場合にのみ機能します)。挿入される行の複数のチャンクに-1つのトランザクションでまとめて保持する必要がある場合は、もちろんそれを行うことはできません)。

または、ここで説明されているように、プログレス バーのマーキー スタイルの使用を検討することもできます。この場合、パーセント値を更新する必要はまったくありません。

于 2013-11-06T15:28:10.853 に答える
0

ワーカー スレッドを生成する方法に関係なく、最初に行う必要があるのは、ユーザーが同じ要求を再度発行できるようにする UI の部分を無効にすることです。そうしないと、ユーザーがボタンを複数回クリックする可能性があります。せっかちです。

バックグラウンドで SQL 作業を行う追加のスレッドを生成するには、BeginExecuteNonQuery 関数を使用し、コマンド オブジェクトを状態変数として渡します (影響を受ける行数を返す必要がある場合)。その呼び出しの直後に進行状況のアニメーションまたはメッセージを表示します。

次に、BeginExecuteNonQuery のコールバック メソッドで、進行アニメーション/テキストを停止/非表示にします。

次に例を示します。

Public Sub InsertNumberswithMsgID(ByVal messageID As Integer, ByVal tableName As String) 

    Dim cmd As SqlCommand = Nothing

    Try
        cmd = New SqlCommand(("dbo.[InsertNumbers_withMsgID]"), cn)
        cmd.CommandType = CommandType.StoredProcedure
        cmd.Parameters.AddWithValue("@tablename", tableName)
        cmd.Parameters.AddWithValue("@msgid", messageID)
        cmd.CommandTimeout = 6000
        If Not cn Is Nothing And cn.State = ConnectionState.Closed Then cn.Open()
        cmd.BeginExecuteNonQuery(FinishInsertingNumbersWithMsgId, cmd)
        ShowYourProgressAnimation()
    Catch ex As SqlException

    Catch ex As Exception

    Finally
        If Not cn Is Nothing And cn.State = ConnectionState.Open Then cn.Close()
        If Not cmd Is Nothing Then cmd.Dispose()
    End Try

End Sub

Private Sub FinishInsertingNumbersWithMsgId(ByVal ar As IAsyncResult)
    Dim cmd As SqlCommand = ar.AsyncState
    cmd.EndExecuteNonEquery(ar)
    HideYourProgressAnimation()
End Sub
于 2013-11-06T15:29:13.793 に答える