Disable Button During Processing & Re-Enable After Processing?

D

Donald A. Fisher

Hello. I've been working a vb project and have a form with a button on
it that performs some actions after disabling the button when clicked:

Code disabling button and starting actions:
Private Sub btnCreateExcel_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnCreateExcel.Click
Me.btnCreateExcel.Enabled = False
Dim pCreateExcel As New ClassCreateExcel
AddHandler pCreateExcel.CreateExcelCompleted, AddressOf
CreateExcelCompletedEventHandler
Dim thCreateExcel As System.Threading.Thread
thCreateExcel = New System.Threading.Thread(AddressOf
pCreateExcel.Process)
thCreateExcel.Start()
End Sub


I've tried using the "CreateExcelCompleteEventHandler to re-enable the
button to no avail:

Code performed after actions are completed:
Private Sub CreateExcelCompletedEventHandler(ByVal sender As
System.Object, ByVal e As System.EventArgs)
frmCreateExcelProgress.Close()
Me.btnCreateExcel.Enabled = True
End Sub


The actions completed really don't matter (I think). I just want the
button to be disabled so the user cannot start multiple events by
double-clicking or being impatient and clicking again and then re-enable
the button after processing has finished. Any help would be great!
Thanks in advance!

Don
 
T

Tom Shelton

Hello. I've been working a vb project and have a form with a button on
it that performs some actions after disabling the button when clicked:

Code disabling button and starting actions:
Private Sub btnCreateExcel_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnCreateExcel.Click
Me.btnCreateExcel.Enabled = False
Dim pCreateExcel As New ClassCreateExcel
AddHandler pCreateExcel.CreateExcelCompleted, AddressOf
CreateExcelCompletedEventHandler
Dim thCreateExcel As System.Threading.Thread
thCreateExcel = New System.Threading.Thread(AddressOf
pCreateExcel.Process)
thCreateExcel.Start()
End Sub


I've tried using the "CreateExcelCompleteEventHandler to re-enable the
button to no avail:

Code performed after actions are completed:
Private Sub CreateExcelCompletedEventHandler(ByVal sender As
System.Object, ByVal e As System.EventArgs)
frmCreateExcelProgress.Close()
Me.btnCreateExcel.Enabled = True
End Sub
The actions completed really don't matter (I think). I just want the
button to be disabled so the user cannot start multiple events by
double-clicking or being impatient and clicking again and then re-enable
the button after processing has finished. Any help would be great!
Thanks in advance!

Don

This maybe a silly question - but is the event even beign fired? And if
it is, your most likely going to have issues because it's going to be
raised from your background thread...

Personally, if your going to do this, you might want to look into using
hte backgroundworker component.
 
D

Donald A. Fisher

Tom said:
This maybe a silly question - but is the event even beign fired? And if
it is, your most likely going to have issues because it's going to be
raised from your background thread...

Personally, if your going to do this, you might want to look into using
hte backgroundworker component.
Yes, the event is fired. I've even added a message box to confirm. I
do, however, get an debugging error that I'm not understanding. At the
beginning of my separate class that performs actions as follows:

Event Code:
Public Event CreateExcelCompleted(ByVal sender As Object, ByVal e As
System.EventArgs)


Then at the end of the class I have this line to call the handler:
RaiseEvent CreateExcelCompleted(Me, New System.EventArgs)


The handler runs the code above under "CreateExcelCompletedEventHandler"
after the class is finished (this is where I've added the message box
and I get it). I'm getting a debug error:

System.InvalidOperationException was unhandled
Message="Cross-thread operation not valid: Control 'btnCreateExcel'
accessed from a thread other than the thread it was created on."
Source="System.Windows.Forms"
StackTrace:
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.Control.OnEnabledChanged(EventArgs e)
at System.Windows.Forms.ButtonBase.OnEnabledChanged(EventArgs e)
at System.Windows.Forms.Control.set_Enabled(Boolean value)
at MT2.frmMain.CreateExcelCompletedEventHandler(Object sender,
EventArgs e) in K:\VBS_05_PROJ\Munitions Task Management Tools
v1.0\Munitions Task Management Tools v1.0\frmMain.vb:line 159
at MT2.ClassCreateExcel.Process() in K:\VBS_05_PROJ\Munitions
Task Management Tools v1.0\Munitions Task Management Tools
v1.0\Class_CreateExcel.vb:line 23
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode
code, CleanupCode backoutCode, Object userData)
at
System.Threading.ExecutionContext.RunInternal(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

when it reaches the line to re-enable the button:

Line to re-enable button:
Me.btnCreateExcel.Enabled = True


This may be a little too detailed and I apologize. I am not familiar
with background workers. I did much reading and found a lot about
threads etc. Am I going about it all wrong? Thanks again.

Don
 
T

Tom Shelton

Yes, the event is fired. I've even added a message box to confirm. I
do, however, get an debugging error that I'm not understanding. At the
beginning of my separate class that performs actions as follows:

Event Code:
Public Event CreateExcelCompleted(ByVal sender As Object, ByVal e As
System.EventArgs)


Then at the end of the class I have this line to call the handler:
RaiseEvent CreateExcelCompleted(Me, New System.EventArgs)


The handler runs the code above under "CreateExcelCompletedEventHandler"
after the class is finished (this is where I've added the message box
and I get it). I'm getting a debug error:

System.InvalidOperationException was unhandled
Message="Cross-thread operation not valid: Control 'btnCreateExcel'
accessed from a thread other than the thread it was created on."
Source="System.Windows.Forms"
StackTrace:
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.Control.OnEnabledChanged(EventArgs e)
at System.Windows.Forms.ButtonBase.OnEnabledChanged(EventArgs e)
at System.Windows.Forms.Control.set_Enabled(Boolean value)
at MT2.frmMain.CreateExcelCompletedEventHandler(Object sender,
EventArgs e) in K:\VBS_05_PROJ\Munitions Task Management Tools
v1.0\Munitions Task Management Tools v1.0\frmMain.vb:line 159
at MT2.ClassCreateExcel.Process() in K:\VBS_05_PROJ\Munitions
Task Management Tools v1.0\Munitions Task Management Tools
v1.0\Class_CreateExcel.vb:line 23
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode
code, CleanupCode backoutCode, Object userData)
at
System.Threading.ExecutionContext.RunInternal(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

when it reaches the line to re-enable the button:

Line to re-enable button:
Me.btnCreateExcel.Enabled = True


This may be a little too detailed and I apologize. I am not familiar
with background workers. I did much reading and found a lot about
threads etc. Am I going about it all wrong? Thanks again.

Don

Don,

As I suspected - you are getting a cross thread access violation. You
can not directly access windows controls outside of the thread on which
they were created. You need to change the code of your method
(something like):


Private Sub CreateExcelCompletedEventHandler(ByVal sender As System.Object, ByVal e As System.EventArgs)
If Me.InvokeRequired Then
Me.Invoke ( _
new EventHandler(Me.CreateExcelCompletedEventHandler), _
new Object() {sender, e))
Else
frmCreateExcelProgress.Close()
Me.btnCreateExcel.Enabled = True
End If
End Sub
 
T

Tom Shelton

Yes, the event is fired. I've even added a message box to confirm. I
do, however, get an debugging error that I'm not understanding. At the
beginning of my separate class that performs actions as follows:

Event Code:
Public Event CreateExcelCompleted(ByVal sender As Object, ByVal e As
System.EventArgs)


Then at the end of the class I have this line to call the handler:
RaiseEvent CreateExcelCompleted(Me, New System.EventArgs)


The handler runs the code above under "CreateExcelCompletedEventHandler"
after the class is finished (this is where I've added the message box
and I get it). I'm getting a debug error:

System.InvalidOperationException was unhandled
Message="Cross-thread operation not valid: Control 'btnCreateExcel'
accessed from a thread other than the thread it was created on."
Source="System.Windows.Forms"
StackTrace:
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.Control.OnEnabledChanged(EventArgs e)
at System.Windows.Forms.ButtonBase.OnEnabledChanged(EventArgs e)
at System.Windows.Forms.Control.set_Enabled(Boolean value)
at MT2.frmMain.CreateExcelCompletedEventHandler(Object sender,
EventArgs e) in K:\VBS_05_PROJ\Munitions Task Management Tools
v1.0\Munitions Task Management Tools v1.0\frmMain.vb:line 159
at MT2.ClassCreateExcel.Process() in K:\VBS_05_PROJ\Munitions
Task Management Tools v1.0\Munitions Task Management Tools
v1.0\Class_CreateExcel.vb:line 23
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode
code, CleanupCode backoutCode, Object userData)
at
System.Threading.ExecutionContext.RunInternal(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

when it reaches the line to re-enable the button:

Line to re-enable button:
Me.btnCreateExcel.Enabled = True


This may be a little too detailed and I apologize. I am not familiar
with background workers. I did much reading and found a lot about
threads etc. Am I going about it all wrong? Thanks again.

Don

Actually, I think this needs a little more explanation:

http://msdn2.microsoft.com/en-us/library/ms951089.aspx

Start there (this is the link to part 1 of a 3 part article) - it's C#, but
the idea is exactly the same. Then, once you've looked at that - look
at the documentation on the BackgroundWorker component, and thank MS for
providing a easier means to accomplish the task your trying to accomplish.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top