Simple thead question .... what am I doing wrong?

M

M O J O

Hi,

I have a little test project. I spin up a thread, lets it sleep for a
second and then the thread makes a button visible ... or at least should
make it visible, which it doesn't do.

---------------------------------------------------------------------------

Here's my thread class:

Imports System.Threading

Public Class MyThreadClass

Private _thread As Thread
Public Delegate Sub ThreadDone(ByVal IsOnline As Boolean)
Public OnThreadDone As ThreadDone


Public Sub Run()
_thread = New Thread(AddressOf Start)
_thread.IsBackground = True
_thread.Start()
End Sub


Public Sub SpinDown()
If _thread Is Nothing Then Exit Sub
_thread.Abort()
_thread = Nothing
End Sub


Public Sub Abort()
If _thread Is Nothing Then Exit Sub
_thread.Abort()
_thread = Nothing
End Sub


Private Sub Start()
Try
_thread.Sleep(1000)
OnThreadDone.Invoke(True)
Catch
OnThreadDone.Invoke(False)
Finally
End Try
End Sub

End Class

---------------------------------------------------------------------------

And here's my form code:

Private _thread As MyThreadClass

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles MyBase.Load
_thread = New MyThreadClass
_thread.OnThreadDone = AddressOf OnThreadDone
_thread.Run()
End Sub


Public Sub OnThreadDone(ByVal status As Boolean)
Me.Button1.Visible = True
' The button is still hidden :blush:(((
End Sub

---------------------------------------------------------------------------

What am I doing wrong??

Why doesn't the button show up?

Thanks in advance!!

M O J O
 
A

Armin Zingler

M O J O said:
Hi,

I have a little test project. I spin up a thread, lets it sleep for a
second and then the thread makes a button visible ... or at least
should
make it visible, which it doesn't do.

-------------------------------------------------------------------------- -

Here's my thread class:

Imports System.Threading

Public Class MyThreadClass

Private _thread As Thread
Public Delegate Sub ThreadDone(ByVal IsOnline As Boolean)
Public OnThreadDone As ThreadDone


Public Sub Run()
_thread = New Thread(AddressOf Start)
_thread.IsBackground = True
_thread.Start()
End Sub


Public Sub SpinDown()
If _thread Is Nothing Then Exit Sub
_thread.Abort()
_thread = Nothing
End Sub


Public Sub Abort()
If _thread Is Nothing Then Exit Sub
_thread.Abort()
_thread = Nothing
End Sub


Private Sub Start()
Try
_thread.Sleep(1000)
OnThreadDone.Invoke(True)
Catch
OnThreadDone.Invoke(False)
Finally
End Try
End Sub

End Class

-------------------------------------------------------------------------- -

And here's my form code:

Private _thread As MyThreadClass

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
_
System.EventArgs) Handles MyBase.Load
_thread = New MyThreadClass
_thread.OnThreadDone = AddressOf OnThreadDone
_thread.Run()
End Sub


Public Sub OnThreadDone(ByVal status As Boolean)
Me.Button1.Visible = True
' The button is still hidden :blush:(((
End Sub

-------------------------------------------------------------------------- -

What am I doing wrong??

Why doesn't the button show up?


Only the thread creating a window/button can access it. In the Form, in
OnThreadDone, Uue Me.Invoke or Me.Button1.Invoke to marshal the call to the
thread creating the form/button.
 
P

Peter Huang

Hi,

When you call a delegate synchronously, the Invoke method calls the target
method directly on the current thread.
For more details, take a look at the link below.
Asynchronous Delegates
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpovrasynchronousdelegates.asp

You may the code below,
Private _thread As MyThreadClass
Public Sub OnThreadDone(ByVal status As Boolean)
Me.Button1.Visible = True
' The button will be visible now :)))
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
_thread = New MyThreadClass
_thread.fm = Me
_thread.OnThreadDone = AddressOf OnThreadDone
_thread.Run()
End Sub

Public Class MyThreadClass
Public fm As Form1
''''Pass in the Form1's reference
Private _thread As Thread
Public Delegate Sub ThreadDone(ByVal IsOnline As Boolean)
Public OnThreadDone As ThreadDone


Public Sub Run()
_thread = New Thread(AddressOf Start)
_thread.IsBackground = True
_thread.Start()
End Sub


Public Sub SpinDown()
If _thread Is Nothing Then Exit Sub
_thread.Abort()
_thread = Nothing
End Sub


Public Sub Abort()
If _thread Is Nothing Then Exit Sub
_thread.Abort()
_thread = Nothing
End Sub
Private Sub Start()
Try
_thread.Sleep(1000)
'Call the form1's invoke, so that the delegate method OnThreadDone will
call on
'Form1's thread
fm.Invoke(OnThreadDone, New Object() {True})
Catch
fm.Invoke(OnThreadDone, New Object() {False})
Finally
End Try
End Sub
End Class

Regards,
Peter Huang
Microsoft Online Partner Support
Get Secure! www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
R

Russell Jones

You've fallen into a classic threading trap--the thread you're using to make
the button visible is not the UI thread.

Here's one way to fix the problem. Add this code to the form.
Private Delegate Sub showButtonDelegate()

Public Sub OnThreadDone(ByVal status As Boolean)
Dim sb As New showButtonDelegate(AddressOf Me.MakeButton1Visible)
If Me.InvokeRequired Then
Me.Invoke(sb)
Else
Me.Button1.Visible = True
End If
' button is now visible
End Sub

Private Sub MakeButton1Visible()
Me.Button1.Visible = True
End Sub

Obviously, you could make the code a little more generic than shown here.
The Invoke method is the key to getting UI actions back on the right thread.
You could just as easily check the InvokeRequired property of the button
object itself and use Invoke or not, as required.
 

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