如何减少 VB.NET 中输出框的延迟?
How can I reduce the delay in my output box in VB.NET?
想法是弹出一个新的 window 弹出窗口,您可以在其中查看正在发生的事情。问题是:在弹出窗口 window 中显示任何内容之前有 20 秒的延迟。我可以验证这一点,因为在控制台输出中我可以直接看到发生了什么。它从弹出窗口 window 的开头开始,在显示所有记录之前弹出窗口消失,因为程序已经提前 20 秒。
任何人都知道如何显示弹出窗口 window 并直接显示输出?
If DgvObj.CheckRecords(100, 1) = 1 Then
Dim dialog As New OutputBox("archive") With {
.Width = 400,
.Height = 200
}
dialog.Show()
dialog.textBox.Text = "Waiting..." & Environment.NewLine
Dim order_num As String
For Each row As DataGridViewRow In DgvObj.DataGridName(1).Rows
order_num = row.Cells("Order").Value
dialog.textBox.AppendText("Archive record " & row.Index + 1 & " Order: " & order_num & Date.Now & Environment.NewLine)
Console.WriteLine("Archive record " & row.Index + 1 & " Order: " & order_num & Date.Now)
FormArchiveren(order_num, True)
Next
dialog.Close()
End If
当您在 windows 应用程序中执行某项操作时,例如单击按钮,按钮点击处理程序中的代码开始计算 Pi 到万亿位小数等,您会阻止处理所有 UI 更新回到其保持 UI 活动和响应的工作。这意味着应用程序中的显示在执行工作时似乎挂起 - 这是一个常见问题,SO 上可能有数以万计的问题询问它
答案总是一样的,而且很简单;不要让处理按钮单击事件的线程花费很长时间来做任何事情。小于 50 毫秒通常是可以的。任何超过 50 毫秒的操作,不要在处理事件处理程序的同一线程上执行
有很多方法可以解决这个问题,最简单也是最麻烦的就是定期告诉 UI 线程,你已经吸引了它的注意力,去处理所有 UI 更新悬而未决;在设置文本框 AppendText
后插入 Application.DoEvents()
最好,一种几乎同样简单的方法是使用 Task-based 异步模式;使您在 FormArchiveren 中所做的工作异步*,使方法 return 成为任务,使您的点击处理程序(或任何启动此过程的事件)异步,并等待 FormArchiveren(order_num, True)
涉及更多编码且如今已失宠的替代方法是使用 BackgroundWorker 或真正的多线程解决方案。它们很少使用,因为它们很难正确使用(尽管 backgroundworker 更容易)
请注意,如果您这样做(TAP、BackgroundWorker 或执行 FormArchiveren 的单独线程),您不应从 FormArchiveren 中访问 UI 控件,因为执行工作的线程不是创建 UI 控制,这是 windows 表单编码的基本原则;除了创建控件的线程之外,您不得使用任何线程来更新有关控件的任何内容
*使 FormArchiveren 异步可能微不足道,或者可能涉及更多,但要就此提供任何明智的建议,我们需要查看它的定义(以及它调用的任何其他内容)这也是你程序的一部分。最简单的是,它会切换到使用它已经调用的同步方法的现有异步版本。如果它自己做了很多同步工作,而没有现有的异步版本,那么设置任务和 运行 他们自己将是“更多参与”位
您可以使用 application.DoEvents
更新统计信息显示
例如:
If DgvObj.CheckRecords(100, 1) = 1 Then
Dim dialog As New OutputBox("archive") With {
.Width = 400,
.Height = 200
}
dialog.Show()
dialog.textBox.Text = "Waiting..." & Environment.NewLine
Application.DoEvents()
Dim order_num As String
For Each row As DataGridViewRow In DgvObj.DataGridName(1).Rows
order_num = row.Cells("Order").Value
dialog.textBox.AppendText("Archive record " & row.Index + 1 & " Order: " & order_num & Date.Now & Environment.NewLine)
Console.WriteLine("Archive record " & row.Index + 1 & " Order: " & order_num & Date.Now)
Applicaton.DoEvents()
FormArchiveren(order_num, True)
Next
dialog.Close()
End If
请注意,即使您接受其他推荐的建议将其移至另一个线程?您将需要使用 doevents 或某种形式的刷新来使该显示在循环和代码运行时更新。因此,虽然一个单独的线程是个好主意,但它不会解决或解决您在代码循环期间遇到的基本问题,您必须在该过程中发出更新显示的命令。
我还应该指出 doevents 很重,如果循环超过 100 行?您想要放入一些代码以仅每 100 行或每半秒触发一次 doevent。因此,对于大型处理,我建议谨慎使用这种方法。
想法是弹出一个新的 window 弹出窗口,您可以在其中查看正在发生的事情。问题是:在弹出窗口 window 中显示任何内容之前有 20 秒的延迟。我可以验证这一点,因为在控制台输出中我可以直接看到发生了什么。它从弹出窗口 window 的开头开始,在显示所有记录之前弹出窗口消失,因为程序已经提前 20 秒。 任何人都知道如何显示弹出窗口 window 并直接显示输出?
If DgvObj.CheckRecords(100, 1) = 1 Then
Dim dialog As New OutputBox("archive") With {
.Width = 400,
.Height = 200
}
dialog.Show()
dialog.textBox.Text = "Waiting..." & Environment.NewLine
Dim order_num As String
For Each row As DataGridViewRow In DgvObj.DataGridName(1).Rows
order_num = row.Cells("Order").Value
dialog.textBox.AppendText("Archive record " & row.Index + 1 & " Order: " & order_num & Date.Now & Environment.NewLine)
Console.WriteLine("Archive record " & row.Index + 1 & " Order: " & order_num & Date.Now)
FormArchiveren(order_num, True)
Next
dialog.Close()
End If
当您在 windows 应用程序中执行某项操作时,例如单击按钮,按钮点击处理程序中的代码开始计算 Pi 到万亿位小数等,您会阻止处理所有 UI 更新回到其保持 UI 活动和响应的工作。这意味着应用程序中的显示在执行工作时似乎挂起 - 这是一个常见问题,SO 上可能有数以万计的问题询问它
答案总是一样的,而且很简单;不要让处理按钮单击事件的线程花费很长时间来做任何事情。小于 50 毫秒通常是可以的。任何超过 50 毫秒的操作,不要在处理事件处理程序的同一线程上执行
有很多方法可以解决这个问题,最简单也是最麻烦的就是定期告诉 UI 线程,你已经吸引了它的注意力,去处理所有 UI 更新悬而未决;在设置文本框 AppendText
后插入Application.DoEvents()
最好,一种几乎同样简单的方法是使用 Task-based 异步模式;使您在 FormArchiveren 中所做的工作异步*,使方法 return 成为任务,使您的点击处理程序(或任何启动此过程的事件)异步,并等待 FormArchiveren(order_num, True)
涉及更多编码且如今已失宠的替代方法是使用 BackgroundWorker 或真正的多线程解决方案。它们很少使用,因为它们很难正确使用(尽管 backgroundworker 更容易)
请注意,如果您这样做(TAP、BackgroundWorker 或执行 FormArchiveren 的单独线程),您不应从 FormArchiveren 中访问 UI 控件,因为执行工作的线程不是创建 UI 控制,这是 windows 表单编码的基本原则;除了创建控件的线程之外,您不得使用任何线程来更新有关控件的任何内容
*使 FormArchiveren 异步可能微不足道,或者可能涉及更多,但要就此提供任何明智的建议,我们需要查看它的定义(以及它调用的任何其他内容)这也是你程序的一部分。最简单的是,它会切换到使用它已经调用的同步方法的现有异步版本。如果它自己做了很多同步工作,而没有现有的异步版本,那么设置任务和 运行 他们自己将是“更多参与”位
您可以使用 application.DoEvents
更新统计信息显示例如:
If DgvObj.CheckRecords(100, 1) = 1 Then
Dim dialog As New OutputBox("archive") With {
.Width = 400,
.Height = 200
}
dialog.Show()
dialog.textBox.Text = "Waiting..." & Environment.NewLine
Application.DoEvents()
Dim order_num As String
For Each row As DataGridViewRow In DgvObj.DataGridName(1).Rows
order_num = row.Cells("Order").Value
dialog.textBox.AppendText("Archive record " & row.Index + 1 & " Order: " & order_num & Date.Now & Environment.NewLine)
Console.WriteLine("Archive record " & row.Index + 1 & " Order: " & order_num & Date.Now)
Applicaton.DoEvents()
FormArchiveren(order_num, True)
Next
dialog.Close()
End If
请注意,即使您接受其他推荐的建议将其移至另一个线程?您将需要使用 doevents 或某种形式的刷新来使该显示在循环和代码运行时更新。因此,虽然一个单独的线程是个好主意,但它不会解决或解决您在代码循环期间遇到的基本问题,您必须在该过程中发出更新显示的命令。
我还应该指出 doevents 很重,如果循环超过 100 行?您想要放入一些代码以仅每 100 行或每半秒触发一次 doevent。因此,对于大型处理,我建议谨慎使用这种方法。