Vb.net 如何在Do循环语句运行时保持窗体的响应性

Vb.net 如何在Do循环语句运行时保持窗体的响应性,vb.net,multithreading,winforms,Vb.net,Multithreading,Winforms,如果运行以下代码,您将看到在运行Do[…]循环语句时无法单击Button2: Imports Microsoft.Office.Interop Public Class Form1 Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click Dim xlApp As New Excel.Application xlApp

如果运行以下代码,您将看到在运行
Do[…]循环
语句时无法单击
Button2

Imports Microsoft.Office.Interop

Public Class Form1

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click

        Dim xlApp As New Excel.Application
        xlApp.Visible = True
        Dim wb1 As Excel.Workbook
        wb1 = xlApp.Workbooks.Open("C:\Book1.xlsx")


        Dim wsSheet1 As Excel.Worksheet
        wsSheet1 = CType(wb1.Sheets(1), Excel.Worksheet)

        Do
            wsSheet1.Cells.Copy()
            wsSheet1.Cells.PasteSpecial(Paste:=Excel.XlPasteType.xlPasteValues)
        Loop

    End Sub

    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        MsgBox("Hello")
    End Sub

End Class

do[…]循环
语句运行时,如何保持
Form1
的响应性?

根据我所读的内容,当您要求您的程序执行特定任务时,您的UI似乎变得没有响应。在这种情况下,您应该查看msdn上的
后台工作程序
示例,或者您可以使用其他线程而不使用后台工作程序,这真的是你的选择。

下面是我写的一个快速示例,它将使用不同的线程在屏幕上随机位置绘制矩形框,这将允许您在窗口绘制到屏幕时移动窗口,并与其他组件进行交互,使它们在不冻结的情况下正常工作,例如
消息框

Imports System.ComponentModel
Public Class Form1
Dim random0 As New Random
Dim thread0 As New Threading.Thread(New Threading.ThreadStart(AddressOf threadDrawing0))

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    thread0.Start()
End Sub
Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
    thread0.Abort()
End Sub

Private Sub threadDrawing0()
    For i = 0 To 1000
        System.Threading.Thread.Sleep(100)
        Me.CreateGraphics().DrawRectangle(New Pen(Brushes.Blue, 4), New Rectangle(random0.Next(0, Me.Width), random0.Next(0, Me.Height), 20, 20))
    Next
End Sub

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    MessageBox.Show("Hello World")
End Sub
End Class

由于我没有您正在使用的excel文件,我无法根据您的具体需要测试代码,但是这应该会让您真正走上正确的道路。

MSDN后台工作人员链接:

,以便在
执行[…]操作时保持表单的响应性循环
语句正在运行,您需要使用类在单独的线程上运行它

首先创建一个新方法,并将
Do[…]循环
语句放在该方法中:

Private Sub CopyCells(ByVal worksheet As Excel.Worksheet)

    Do
        worksheet.Cells.Copy()
        worksheet.Cells.PasteSpecial(Paste:=Excel.XlPasteType.xlPasteValues)
    Loop

End Sub
然后,您可以使用以下方法调用此方法:

我也不再使用
MsgBox
,而是使用
MessageBox.Show
MsgBox
适用于VB6,并最终授权给
MessageBox
,因此使用
MessageBox是有意义的。Show

MessageBox.Show("Hello")
总的来说,您的代码看起来与此类似:

Public Class Form1

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click

        Dim xlApp As New Excel.Application
        xlApp.Visible = True

        Dim wb1 As Excel.Workbook
        wb1 = xlApp.Workbooks.Open("C:\Book1.xlsx")

        Dim wsSheet1 As Excel.Worksheet
        wsSheet1 = CType(wb1.Sheets(1), Excel.Worksheet)

        Task.Factory.StartNew(Sub() CopyCells(wsSheet1))

    End Sub

    Private Sub CopyCells(ByVal worksheet As Excel.Worksheet)

        Do
            worksheet.Cells.Copy()
            worksheet.Cells.PasteSpecial(Paste:=Excel.XlPasteType.xlPasteValues)
        Loop

    End Sub

    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        MessageBox.Show("Hello")
    End Sub

End Class
请注意,您必须导入
System.Threading.Tasks
才能使用
Task


如果您希望UI在长时间运行的任务中具有响应性,则必须使用辅助线程。这可以通过多种方式完成,包括使用
任务
类。不幸的是,这不是编码服务。你需要自己尝试一下,然后如果你有问题,有人会帮助你解决。
Public Class Form1

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click

        Dim xlApp As New Excel.Application
        xlApp.Visible = True

        Dim wb1 As Excel.Workbook
        wb1 = xlApp.Workbooks.Open("C:\Book1.xlsx")

        Dim wsSheet1 As Excel.Worksheet
        wsSheet1 = CType(wb1.Sheets(1), Excel.Worksheet)

        Task.Factory.StartNew(Sub() CopyCells(wsSheet1))

    End Sub

    Private Sub CopyCells(ByVal worksheet As Excel.Worksheet)

        Do
            worksheet.Cells.Copy()
            worksheet.Cells.PasteSpecial(Paste:=Excel.XlPasteType.xlPasteValues)
        Loop

    End Sub

    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        MessageBox.Show("Hello")
    End Sub

End Class