Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / VB.NET / October 2004

Tip: Looking for answers? Try searching our database.

Why Does This Fail ( Threading )

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
One Handed Man \( OHM - Terry Burns \) - 21 Oct 2004 17:15 GMT
Assumes a Form with a Panel on it., Does the Mutex have to be within the
address of a thread start address ?

Cheers - OHM

'-----------   ***************   ----------------

Private endProgram As Boolean = False

Dim image1 As Image = Image.FromFile("..\Images\gun.bmp")

Dim image2 As Image = Image.FromFile("..\Images\Invader.bmp")

Dim space As Graphics

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

Dim Thread1 As New Threading.Thread(AddressOf Me.WriteImage1)

Dim Thread2 As New Threading.Thread(AddressOf Me.WriteImage2)

space = Panel1.CreateGraphics()

Thread1.Start()

Thread2.Start()

End Sub

Private Sub WriteImage1()

While Not endProgram

DrawImage(space, image1, New Point(10, 10))

End While

End Sub

Private Sub WriteImage2()

While Not endProgram

DrawImage(space, image2, New Point(50, 50))

End While

End Sub

Public Sub DrawImage(ByVal g As Graphics, ByVal i As Image, ByVal p As
Point)

Dim m As New Threading.Mutex

m.WaitOne()

g.DrawImage(i, p)

m.ReleaseMutex()

End Sub

Signature

OHM ( Terry Burns )   * Use the following to email me *

Dim ch() As Char = "ufssz/cvsotAhsfbuTpmvujpotXjui/OFU".ToCharArray()
For i As Int32 = 0 To ch.Length - 1
    ch(i) = Convert.ToChar(Convert.ToInt16(ch(i)) - 1)
Next
Process.Start("mailto:" & New String(ch))
--

Larry Serflaten - 21 Oct 2004 18:55 GMT
"One Handed Man ( OHM - Terry Burns )" <news.microsoft.com> wrote
> Assumes a Form with a Panel on it., Does the Mutex have to be within the
> address of a thread start address ?

I would think it would have to be declared at a larger scope than the
procedure you need it in.  I looks to me like you create and destroy a new
mutex for each call....

LFS

> Public Sub DrawImage(ByVal g As Graphics, ByVal i As Image, ByVal p As
> Point)
[quoted text clipped - 8 lines]
>
> End Sub
One Handed Man \( OHM - Terry Burns \) - 21 Oct 2004 21:59 GMT
Tried decaling the Mutex in a module,that didnt work either

Signature

OHM ( Terry Burns )   * Use the following to email me *

Dim ch() As Char = "ufssz/cvsotAhsfbuTpmvujpotXjui/OFU".ToCharArray()
For i As Int32 = 0 To ch.Length - 1
    ch(i) = Convert.ToChar(Convert.ToInt16(ch(i)) - 1)
Next
Process.Start("mailto:" & New String(ch))
--

> "One Handed Man ( OHM - Terry Burns )" <news.microsoft.com> wrote
>> Assumes a Form with a Panel on it., Does the Mutex have to be within the
[quoted text clipped - 18 lines]
>>
>> End Sub
Larry Serflaten - 22 Oct 2004 09:57 GMT
"One Handed Man ( OHM - Terry Burns )" <news.microsoft.com> wrote
> Tried decaling the Mutex in a module,that didnt work either

I suggested using a delegate.  Try this out in a new form with one button.
Paste in the code after the designer code.

Also as I was building this up, it occured to me that some sort of pooling
should be used, should it not?  Invaders come and go over the course of the
game, so pooling may let the system managed them a little better....

HTH
LFS

   Private GrxForm As Graphics
   Private th1, th2 As Threading.Thread
   Private brh As SolidBrush = New SolidBrush(Color.Black)
   Private rnd As Random = New Random
   Private fnt As Font = New Font("tahoma", 24, FontStyle.Bold)

   Delegate Sub Drawing(ByVal ID As Integer, ByVal Loc As PointF)
   Private Dlg As New Drawing(AddressOf CommonDraw)

   Private Done As Boolean

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
       GrxForm = Me.CreateGraphics
       Th1 = New Threading.Thread(AddressOf Thread1)
       Th2 = New Threading.Thread(AddressOf Thread2)
       Th1.Start()
       Th2.Start()
   End Sub

   Private Sub CommonDraw(ByVal ID As Integer, ByVal Loc As PointF)
       Dim klr As Color = Color.FromArgb(200, rnd.Next(0, 256), rnd.Next(0, 256), rnd.Next(0, 256))
       ' The Brush, Font and Graphics are shared
       brh.Color = klr
       GrxForm.FillRectangle(brh, Loc.X, Loc.Y, 80, 50)
       GrxForm.DrawString(CStr(ID), fnt, Brushes.Black, Loc)
   End Sub

   Sub Thread1()
       Dim id As Integer = 1
       Dim loc As PointF = New PointF(10, 10)
       Do While Not Done
           Me.Invoke(Dlg, New Object() {id, loc})
           Threading.Thread.Sleep(100)
       Loop
   End Sub

   Sub Thread2()
       Dim id As Integer = 2
       Dim loc As PointF = New PointF(100, 10)
       Do While Not Done
           Me.Invoke(Dlg, New Object() {id, loc})
           Threading.Thread.Sleep(100)
       Loop
   End Sub

   Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
       e.Cancel = Done
       Done = True
       Application.DoEvents()
       Th1.Abort()
       Th2.Abort()
   End Sub
Larry Serflaten - 22 Oct 2004 10:02 GMT
>     Private Sub Form1_Closing(...)
>         e.Cancel = Done
[quoted text clipped - 3 lines]
>         Th2.Abort()
>     End Sub

Should have been:

 e.Cancel = Not Done

It was meant to cause the first hit on the close button to stop the
threads (they take a while to close down) and the second hit to
close the form....  

(Rather than add another button to stop the threads...)

LFS
One Handed Man \( OHM - Terry Burns \) - 22 Oct 2004 12:54 GMT
Thanks Larry,

I've tried your code out and it seems fine, I'll see if I can work it in to
my code and observe the results. Threading is not something Ive had to do
much of, so these kinds of issues have not arisen for me.  It just goes to
show that real work problems provide the best excercies to promote learning.

Signature

OHM ( Terry Burns )   * Use the following to email me *

Dim ch() As Char = "ufssz/cvsotAhsfbuTpmvujpotXjui/OFU".ToCharArray()
For i As Int32 = 0 To ch.Length - 1
    ch(i) = Convert.ToChar(Convert.ToInt16(ch(i)) - 1)
Next
Process.Start("mailto:" & New String(ch))
--

>>     Private Sub Form1_Closing(...)
>>         e.Cancel = Done
[quoted text clipped - 15 lines]
>
> LFS
One Handed Man \( OHM - Terry Burns \) - 22 Oct 2004 17:24 GMT
Actually, thinking about this more before I try and implement it.

My Invader and Gun classes are responsible for doing their own drawing, in
this case they both have to use the/a delegate in which case perhaps I need
to raise an event as they do not have an Invoke method as a form does.

Sorry, but I feel really feel like I cant think my way out of a paper bag
today :(

Signature

OHM ( Terry Burns )   * Use the following to email me *

Dim ch() As Char = "ufssz/cvsotAhsfbuTpmvujpotXjui/OFU".ToCharArray()
For i As Int32 = 0 To ch.Length - 1
    ch(i) = Convert.ToChar(Convert.ToInt16(ch(i)) - 1)
Next
Process.Start("mailto:" & New String(ch))
--

>>     Private Sub Form1_Closing(...)
>>         e.Cancel = Done
[quoted text clipped - 15 lines]
>
> LFS
One Handed Man \( OHM - Terry Burns \) - 23 Oct 2004 11:13 GMT
Hi Larry,

I have implemented your solution in my code and it works. However, the way I
had to do this was to pass a reference of the form to the Class Invader and
Gun, this way I could do the Invoke of the method on the UI Thread in the
form.

Is this the way you would have done it ?

Thanks

Signature

OHM ( Terry Burns )   * Use the following to email me *

Dim ch() As Char = "ufssz/cvsotAhsfbuTpmvujpotXjui/OFU".ToCharArray()
For i As Int32 = 0 To ch.Length - 1
    ch(i) = Convert.ToChar(Convert.ToInt16(ch(i)) - 1)
Next
Process.Start("mailto:" & New String(ch))
--

>>     Private Sub Form1_Closing(...)
>>         e.Cancel = Done
[quoted text clipped - 15 lines]
>
> LFS
Larry Serflaten - 23 Oct 2004 13:26 GMT
"One Handed Man ( OHM - Terry Burns )" <news.microsoft.com> wrote
> I have implemented your solution in my code and it works. However, the way I
> had to do this was to pass a reference of the form to the Class Invader and
> Gun, this way I could do the Invoke of the method on the UI Thread in the
> form.
>
> Is this the way you would have done it ?

You are using a design I would have avoided.  If you are trying to duplicate
'Space Invaders' then you'd have rows of aliens that march side to side as
they advance toward the player.

Because the whole row advances, and moves as a unit, I would have tried
to make a class that handles the whole row.  In addition to fewer objects,
I'd be copying an image of the whole row over at a time, and not each
individual invader.

But, with that said, it may be this is more of an exercise in using threads,
which is OK, if that is what you are really after....

At first glance, it seems you should be using a collection (of some sort) to
house all the invaders that are currently being used.  I would think the call
from the invaders should be made to their container, to interact with the
outside world.  That would mean the invaders call on a method of their
collection object, who forwards their call to the form.  That forwarding
routine should add a check to be sure the form reference is still valid
before forwarding the call.

While that may be a more refined approach, it may just be more practical
to make the form available globally (project wide) and let the invaders
call it direct.

Because that second method would be easy to code and understand, that
is probably what I would do.  A few choice (global) references is sometimes
necessary to simplify a large part of the program.  This certainly seems to
be one of those times....

While some may discourage using global variables, and avoid them at all
costs, I am not that strict.  It pays off, on occasion, to make a few objects
globally available.  To those who think otherwise, I would simply ask them
how they would call DoEvents, if the Application object wasn't available,
or other such common tasks that are included in (what appears to be) globally
available objects....

Do as you see fit.  I favor a simple design when it will work well, so in this
case, a global variable seems appropreate for the job....

LFS
One Handed Man \( OHM - Terry Burns \) - 23 Oct 2004 14:22 GMT
Thanks very much for your help here, it has assisted me greatly.

I am not really trying to build a proper space invaders as you correctly
suggest, just trying to get a handle on threading issues which is something
I have not had to do 'much' of in the past other than one or two cursory
routines which would have tripped the UI.

I think I picked an awkward example unbeknown to me, however, it has served
to illustrate several points to me as far as design consideration is
concerned.

Thanks Again  . . .

Best Regards - OHM
Signature

OHM ( Terry Burns )   * Use the following to email me *

Dim ch() As Char = "ufssz/cvsotAhsfbuTpmvujpotXjui/OFU".ToCharArray()
For i As Int32 = 0 To ch.Length - 1
    ch(i) = Convert.ToChar(Convert.ToInt16(ch(i)) - 1)
Next
Process.Start("mailto:" & New String(ch))
--

> "One Handed Man ( OHM - Terry Burns )" <news.microsoft.com> wrote
>> I have implemented your solution in my code and it works. However, the
[quoted text clipped - 55 lines]
>
> LFS
Ken Tucker [MVP] - 21 Oct 2004 19:28 GMT
Hi,

       First cant update the ui from a thread.
http://msdn.microsoft.com/msdnmag/issues/04/05/BasicInstincts/

       Second.  You might be better of with synclock instead a mutex

Public Sub DrawImage(ByVal g As Graphics, ByVal i As Image, ByVal p As
Point)

synclock g

g.DrawImage(i, p)

end synclock
End Sub

Ken
-----------------
Assumes a Form with a Panel on it., Does the Mutex have to be within the
address of a thread start address ?

Cheers - OHM

'-----------   ***************   ----------------

Private endProgram As Boolean = False

Dim image1 As Image = Image.FromFile("..\Images\gun.bmp")

Dim image2 As Image = Image.FromFile("..\Images\Invader.bmp")

Dim space As Graphics

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

Dim Thread1 As New Threading.Thread(AddressOf Me.WriteImage1)

Dim Thread2 As New Threading.Thread(AddressOf Me.WriteImage2)

space = Panel1.CreateGraphics()

Thread1.Start()

Thread2.Start()

End Sub

Private Sub WriteImage1()

While Not endProgram

DrawImage(space, image1, New Point(10, 10))

End While

End Sub

Private Sub WriteImage2()

While Not endProgram

DrawImage(space, image2, New Point(50, 50))

End While

End Sub

Public Sub DrawImage(ByVal g As Graphics, ByVal i As Image, ByVal p As
Point)

Dim m As New Threading.Mutex

m.WaitOne()

g.DrawImage(i, p)

m.ReleaseMutex()

End Sub

Signature

OHM ( Terry Burns )   * Use the following to email me *

Dim ch() As Char = "ufssz/cvsotAhsfbuTpmvujpotXjui/OFU".ToCharArray()
For i As Int32 = 0 To ch.Length - 1
    ch(i) = Convert.ToChar(Convert.ToInt16(ch(i)) - 1)
Next
Process.Start("mailto:" & New String(ch))
--

One Handed Man \( OHM - Terry Burns \) - 21 Oct 2004 21:59 GMT
tried Synclock, that doesent seem to work

Signature

OHM ( Terry Burns )   * Use the following to email me *

Dim ch() As Char = "ufssz/cvsotAhsfbuTpmvujpotXjui/OFU".ToCharArray()
For i As Int32 = 0 To ch.Length - 1
    ch(i) = Convert.ToChar(Convert.ToInt16(ch(i)) - 1)
Next
Process.Start("mailto:" & New String(ch))
--

> Hi,
>
[quoted text clipped - 80 lines]
>
> End Sub
CJ Taylor - 21 Oct 2004 19:58 GMT
Don't declare the mutex at the procedure level, perhaps try to  at the
module/class level.  Otherwise, each time you enter the procedure you create
a new (and unnamed) mutex variable which the other thread doesn't care
about.  So of course it tries to write.

Alright, so after doing some more reading, was looking at the waithandle and
how that works.  Look into AutoResetEvent, in which case its defined as the
threads communicating through events...  I can help more in a minute, but
have to finish something else now and wanted to get this out to you.  It
inherits from WaitHandle (same as Mutex waitone).  but has a few more
options that do the dirty work under the sheets...

Check it out and let me know if it helps..
-CJ

I'll write more shortly.

> Assumes a Form with a Panel on it., Does the Mutex have to be within the
> address of a thread start address ?
[quoted text clipped - 58 lines]
>
> End Sub
One Handed Man \( OHM - Terry Burns \) - 21 Oct 2004 22:00 GMT
tried declaring at module level, that didnt work. Tried Synclock, that didnt
work either

Signature

OHM ( Terry Burns )   * Use the following to email me *

Dim ch() As Char = "ufssz/cvsotAhsfbuTpmvujpotXjui/OFU".ToCharArray()
For i As Int32 = 0 To ch.Length - 1
    ch(i) = Convert.ToChar(Convert.ToInt16(ch(i)) - 1)
Next
Process.Start("mailto:" & New String(ch))
--

> Don't declare the mutex at the procedure level, perhaps try to  at the
> module/class level.  Otherwise, each time you enter the procedure you
[quoted text clipped - 81 lines]
>>
>> End Sub
CJ Taylor - 22 Oct 2004 01:23 GMT
Try AutoResetEvent

> tried declaring at module level, that didnt work. Tried Synclock, that
> didnt work either
[quoted text clipped - 84 lines]
>>>
>>> End Sub
One Handed Man \( OHM - Terry Burns \) - 22 Oct 2004 08:12 GMT
Same problem

Signature

OHM ( Terry Burns )   * Use the following to email me *

Dim ch() As Char = "ufssz/cvsotAhsfbuTpmvujpotXjui/OFU".ToCharArray()
For i As Int32 = 0 To ch.Length - 1
    ch(i) = Convert.ToChar(Convert.ToInt16(ch(i)) - 1)
Next
Process.Start("mailto:" & New String(ch))
--

> Try AutoResetEvent
>
[quoted text clipped - 90 lines]
>>>>
>>>> End Sub
CJ Taylor - 22 Oct 2004 13:22 GMT
Alright... lets go into more detail... how is it failing...

> Same problem
>
[quoted text clipped - 92 lines]
> >>>>
> >>>> End Sub
One Handed Man \( OHM - Terry Burns \) - 22 Oct 2004 14:46 GMT
If you past my code into a form and add a panel etc, you will see. If comes
back with a "Object in use elsewhere", Larry posted some code which I tried
in the configuration in which he tested it and it seemed to work. I was
going to try it out in my code and see what transpires. I'm not particulary
experienced at threading so this is newish to me.

Signature

OHM ( Terry Burns )   * Use the following to email me *

Dim ch() As Char = "ufssz/cvsotAhsfbuTpmvujpotXjui/OFU".ToCharArray()
For i As Int32 = 0 To ch.Length - 1
    ch(i) = Convert.ToChar(Convert.ToInt16(ch(i)) - 1)
Next
Process.Start("mailto:" & New String(ch))
--

> Alright... lets go into more detail... how is it failing...
>
[quoted text clipped - 112 lines]
>> >>>>  Process.Start("mailto:" & New String(ch))
>> >>>> --

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.