Reputation:
If you run the following code you will see that you can not click Button2
whilst the Do[...]Loop
statement is running:
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
How do you keep Form1
responsive whilst the Do[...]Loop
statement is running?
Upvotes: 1
Views: 724
Reputation: 4489
In order to keep your form responsive whilst the Do[...]Loop
statement is running you need to run it on a separate thread using the Task class.
First create a new method and place the Do[...]Loop
statement in that method:
Private Sub CopyCells(ByVal worksheet As Excel.Worksheet)
Do
worksheet.Cells.Copy()
worksheet.Cells.PasteSpecial(Paste:=Excel.XlPasteType.xlPasteValues)
Loop
End Sub
You can then call this method using Task.Factory.StartNew:
Task.Factory.StartNew(Sub() CopyCells(wsSheet1))
I would also move away from using MsgBox
and use MessageBox.Show
. MsgBox
exists for VB6 and ends up delegating to MessageBox
anyway so makes sense to use MessageBox.Show
:
MessageBox.Show("Hello")
In full your code would look something similar to this:
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
Note that you will have to import
System.Threading.Tasks
to make use of theTask
class.
Upvotes: 0
Reputation: 996
From what I have read, it sounds like your UI is becoming unresponsive when you are asking your program to do a particular task
In this case you should look into the Background Worker
examples on msdn or you could use another thread without using the Background Worker, it really your choice.
Here is a quick example I have written up that will draw rectangle boxes to the screen in a random position using a different thread, this will allow you to move the window around while it draws to the screen and to interact with other components and have them work correctly without it freezing such as a MessageBox
.
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
Because I dont have the excel file you are working with, I am unable to test the code to your exact needs, however this should well and truly get you on the right path.
MSDN Background Worker Link : https://msdn.microsoft.com/es-es/library/cc221403(v=vs.95).aspx
Upvotes: 1