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 提到的文章确实是一个很好的起点 - 将其用作代码的框架,并将函数调用放置在 sleep 命令所在的位置。

但是在您提供的示例中,实际上并没有一种方法来更新进度条中的进度,因为存储过程一步完成所有操作并在完成时返回。

因此,通过这种方式,您将在执行前显示 0%,然后在完成后显示 100%。

或者您必须更改存储过程,以便可以更精细地调用它,即每次处理 10% 的行,然后返回 - 这将允许您更新进度条(只有在您被允许拆分时才有效)插入要插入的多个行块中-如果您需要在一个事务中将其保持在一起,那么您当然不能这样做)。

或者,您可以考虑使用进度条的 Marquee 样式,如此处所述。在这种情况下,您根本不需要更新百分比值。

于 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 回答