Computer Hope

Software => Computer programming => Topic started by: devcom on January 02, 2009, 07:19:59 AM

Title: Visual Studio 2008 - VB - Background work
Post by: devcom on January 02, 2009, 07:19:59 AM
Code:
Code: [Select]
Imports System.Threading

Public Class Form1
    Dim MathBPM As Integer
    Dim ForNum As Integer


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If Not TextBox1.Text = "" Then

            If Button1.Text = "Start" Then
                If RadioButton1.Checked = True Then
                    MathBPM = TextBox1.Text / 60 * 1000
                End If
                If RadioButton2.Checked = True Then
                    MathBPM = TextBox1.Text * 1000
                End If
                Play()
            End If
        End If

    End Sub

    Sub Play()
        ForNum = TextBox2.Text
        While ForNum > 0
            My.Computer.Audio.Play(My.Resources.BPM, AudioPlayMode.Background)
            Thread.Sleep(MathBPM)
            ForNum -= 1
        End While
    End Sub

i want to call Play() in background so i can use stop button / change text of Button1 to "Stop" , but with this code it freeze and wait for complete loop.

I was trying using timer but without luck, same with BackgroundWorker, is this possible to do that ?
Title: Re: Visual Studio 2008 - VB - Background work
Post by: macdad- on January 02, 2009, 11:31:12 AM
so you want it in Sub Play to repeat while ForNum is greater than 0.

how about you try this in the While condition
Code: [Select]
While Not ForNum = 0
Hope this helps
,Nick(macdad-)
Title: Re: Visual Studio 2008 - VB - Background work
Post by: devcom on January 02, 2009, 12:30:48 PM
no i mean if i set ForNum to 50 so it will do 50 loops but it will freeze the progoram and i can't press any button.

I want to make that loop in background so i can press stop button if i want to stop playing sound in this loop
Title: Re: Visual Studio 2008 - VB - Background work
Post by: macdad- on January 02, 2009, 12:38:50 PM
you would have to lose the Thread.Sleep if you wanted to interupt it.

but other than that, it would just continue the loop. and i cant see any other way, since im still a begginer. but perhaps BC will have a better idea. I'll PM him and see i he cant help
Title: Re: Visual Studio 2008 - VB - Background work
Post by: BC_Programmer on January 02, 2009, 01:07:31 PM
hi peeps.  ;D

I don't really use VB.NET; and VB6 is single-threaded almost all the way. Strangely I could have some kind of fake multitasking using the Windows API SetTimer() and KillTimer routines...


I think it worked because I would call SetTimer with a low interval; then my code would continue. Then, after the interval, Windows would execute my callback routine, which would start the "background" process, which for all intents and purposes, seemed to be in a separate thread, but at the same time wasn't.


I came up with something, but there is a caveat.


Code: [Select]

Imports System.Threading
Public Class Form1
    Dim MathBPM As Integer
    Dim forNum As Integer
    Private WithEvents Currsound As System.Media.SoundPlayer



    Private Sub cmdPlayStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdPlayStop.Click

        If cmdPlayStop.Text = "&Play" Then
            'play the sound...
            Try
                Currsound = New System.Media.SoundPlayer(Txtfilename.Text)
                Currsound.Play()
                cmdPlayStop.Text = "&Stop"
            Catch
                Currsound = Nothing
                MsgBox("Error occured playing sound:" & Err.Description, MsgBoxStyle.Critical)
            End Try

        Else
            Currsound.Stop()
            cmdPlayStop.Text = "&Play"

        End If
        '





    End Sub

    Private Sub Currsound_SoundLocationChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Currsound.SoundLocationChanged
        Currsound.Stop()
    End Sub
End Class

anyway- the caveat-

it works for playing files in the background, but the object doesn't appear to have a way to find out if the sound has stopped, and no event exists for that either.

It works great for playing a sound in the background, though.



This is one of the reasons I stay away from the My Namespace...


Title: Re: Visual Studio 2008 - VB - Background work
Post by: macdad- on January 02, 2009, 01:17:13 PM
thanks for dropping in
Title: Re: Visual Studio 2008 - VB - Background work
Post by: devcom on January 02, 2009, 01:38:33 PM
it works but without Currsound.Stop() wich gives me NullReferenceException was unhandled (whatever it means) and how about doeing this in loop ?

And i think i told bad info about that stop button.

I was trying to make infinite loop with that sound (its 2 sec long) and stop button would exit this loop.
Seems hard at all.  ::)

Anyway thanks
Title: Re: Visual Studio 2008 - VB - Background work
Post by: devcom on January 02, 2009, 04:17:00 PM
ok i've done this:

Code: [Select]
Dim PlayThread As New System.Threading.Thread(AddressOf Play)
Code: [Select]
Private Sub Play()
        While Button3.Visible = True
            'Klick.FillColor = Color.Red
            My.Computer.Audio.Play(My.Resources.Sound1, AudioPlayMode.Background)
            'Klick.FillColor = Color.Black
            Thread.Sleep(MathBPM)
        End While

but now when i exit using X it wont cloase all threads, and if i want change Klick.FillColor it gives me error, i've searched the web and found to use Invoke wich is my second problem
Title: Re: Visual Studio 2008 - VB - Background work
Post by: BC_Programmer on January 03, 2009, 09:33:46 AM
With the new info you've provided, it actually becomes much easier. I will create the new code, this time actually testing the call to Stop().

I was thinking you wanted to play the song once, and the button changes to stop while the sound is playing, and returns if it finishes in the meantime. be right back  ;D
Title: Re: Visual Studio 2008 - VB - Background work
Post by: BC_Programmer on January 03, 2009, 09:41:19 AM
I've returned!

Just to clarify, this needs the button to be named cmdPlayStop, and the textbox to be called txtFileName. (much better then button1 and text1, don't you think?)

It works flawlessly on my computer. Let me know of any issues. I wrapped the call to Stop() with a test to check for Nothing, so it won't crash.

Code: [Select]
Imports System.Threading
Public Class Form1
   
    Private Currsound As System.Media.SoundPlayer



    Private Sub cmdPlayStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdPlayStop.Click

        If cmdPlayStop.Text = "&Play" Then
            'play the sound...
            Try
                Currsound = New System.Media.SoundPlayer(Txtfilename.Text)
                Currsound.PlayLooping()
                cmdPlayStop.Text = "&Stop"
            Catch
                '         Currsound = Nothing
                MsgBox("Error occured playing sound:" & Err.Description, MsgBoxStyle.Critical)
            End Try

        Else
            If Not Currsound Is Nothing Then
                Currsound.Stop()
                cmdPlayStop.Text = "&Play"
            Else
                Debug.Print("cannot stop sound: Is Nothing!")

            End If
            ''
        End If




    End Sub

   
End Class
Title: Re: Visual Studio 2008 - VB - Background work
Post by: devcom on January 03, 2009, 02:04:25 PM
Yea it worked ! ;D Didn't know its possible in single thread  ;)

But...

Why you use "&Play" insted of just "Play" ?

And i'm doing Metronome (that used when you play guitar) so it needs some pause before playing next time.

My actual code looks like this:
Code: [Select]
Imports System.Threading

Public Class Form1
    Dim MathBPM As Integer
    Dim TNum As Integer
    Dim Sound As String
    Dim PlayThread As New System.Threading.Thread(AddressOf Play)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If Not TextBox1.Text = "0" Then
            If RadioButton1.Checked = True Then
                MathBPM = (60 / TextBox1.Text) * 1000        '<---- Beats Per Minute
            End If
            If RadioButton2.Checked = True Then
                MathBPM = TextBox1.Text * 1000        '<---- Seconds
            End If

            Sound = ComboBox1.Text

            If TNum = 1 Then
                Button3.Visible = True
                Button1.Enabled = False
                PlayThread.Resume()
            Else
                Button3.Visible = True
                Button1.Enabled = False
                PlayThread.Start()
            End If
        End If
    End Sub

    Private Sub Play()

        While Button3.Visible = True

            If Sound = "Sound1" Then My.Computer.Audio.Play(My.Resources.Sound1, AudioPlayMode.Background)
            If Sound = "Sound2" Then My.Computer.Audio.Play(My.Resources.Sound2, AudioPlayMode.Background)
            'If Sound = "Sound3" Then My.Computer.Audio.Play(My.Resources.Sound3, AudioPlayMode.Background)

            Thread.Sleep(MathBPM)
        End While

    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        'PlayThread.Abort()          <------- This Don't Work
        Close()
    End Sub

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        PlayThread.Suspend()
        Button3.Visible = False
        Button1.Enabled = True
        TNum = 1
    End Sub
End Class

I've done playing in loop and that stop button, but now when i close App the Play() thread its still in task so i need to press Ctr+Alt+Del to close it

Thanks for lesson anyway ;)
Title: Re: Visual Studio 2008 - VB - Background work
Post by: BC_Programmer on January 04, 2009, 10:11:20 AM

are you able to lengthen the sound being looped? this will introduce the pause your looking for if you add some slinece to the start or end.

instead of looping until the button is invisible, why not loop until you change a global variable to "true"?

Then at the end of the play() code, change it back to false.



and the "&Play", and "&Stop" are just old habits of mine; they set the button mnemonic- notice the underline beneath P when using "&Play". This allows you to press Alt+P to "click" the button.


Form1... Button1... Button2...

Come on people. name your controls with proper names. This helps identify the buttons purpose in code, and makes it appear neater.


I even name them for "test" applications, such as the one I made for this one. even with the "cmd" prefix for commandbutton...
Title: Re: Visual Studio 2008 - VB - Background work
Post by: devcom on January 04, 2009, 12:22:06 PM
global variable ?? You mean what ?

And you know how to close this second thread ?

PS:
Button1 - Start
Button3 - Stop
Button2 - Exit
Title: Re: Visual Studio 2008 - VB - Background work
Post by: BC_Programmer on January 04, 2009, 12:31:02 PM
Actually- I should have said Form-level variable.


at the top of your form, underneath the Class declaration (Class Form1) but before any other code.
Code: [Select]
Private mTerminateThread as Boolean

this makes the variable available to all procedures in the form.

this way, in the thread you wish to terminate, you simply loop on mterminatethread:
Code: [Select]
Do While(mterminatethread)

   'thread code...

 Loop

Additionallu, if you're playing the sounds in the background in your thread, it won't work, since  control will be returned before the sound finishes. If you are making it a separate thread (I might also mention that I have NEVER used a separate thread for ANYTHING, and have made a fair number of applications that less Single-thread savvy programmers would use hundreds of threads for.

Also, threads make everything a giant PITA to debug.

Anyway... where was I? Oh yes, if you're making it a separate thread, there is no need to ensure the thread keeps running. Instead of running the sound in the background, you should play is synchronously.
Title: Re: Visual Studio 2008 - VB - Background work
Post by: devcom on January 05, 2009, 07:28:36 AM
but you mean in single thread ? like:

Code: [Select]
Sub Main()

'code

Do While(mterminatethread)

   'thread code...

 Loop

'code

End Sub
or multi:

Code: [Select]
Sub Main()

'code

Play()

End Sub



Sub Play()

Do While(mterminatethread)

   'thread code...

 Loop

End Sub



and there is no command like
Code: [Select]
Form_OnExit or sth like that ??
Title: Re: Visual Studio 2008 - VB - Background work
Post by: devcom on January 05, 2009, 07:56:06 AM
YAY ! ;D Got this done allready  ;D

Found this on internet:

Code: [Select]
Public Class Form1
    Dim accessLock As New Object
    Dim endThread As Boolean = False
    Dim PlayThread As New System.Threading.Thread(AddressOf CodeInThread)

    Private Sub CodeInThread()
        Dim keepRunning As Boolean = True

        While keepRunning 'keeps thread running forever


            'We lock, because that is one way of ensuring that no other thread
            'is accessing the same variables at the same time
            SyncLock accessLock
                If endThread Then
                    keepRunning = False
                End If
            End SyncLock
        End While 'loop forever until keepRunning = False

        'keepRunning now equals false
        'put cleanup code here

        'when the sub finishes, the thread ends
    End Sub

    Public Sub StopThread()
        SyncLock accessLock
            endThread = True
        End SyncLock
    End Sub

    Private Sub StopBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StopBtn.Click
        StopThread()
    End Sub

    Private Sub StartBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartBtn.Click
        PlayThread.Start()
    End Sub
End Class

everythink its working now thanks for helping  ;D ::)
Title: Re: Visual Studio 2008 - VB - Background work
Post by: BC_Programmer on January 05, 2009, 09:15:56 AM
lol, that's the method I just described  ;D
Title: Re: Visual Studio 2008 - VB - Background work
Post by: devcom on January 05, 2009, 11:43:44 AM
lol, didnt know you are talking about that  ::)
Title: Re: Visual Studio 2008 - VB - Background work
Post by: BC_Programmer on January 05, 2009, 11:45:20 AM
well, it uses a form-level variable to flag when the thread should end. that was what I meant.

good to hear you got it workin.

what is this for? Just curious.
Title: Re: Visual Studio 2008 - VB - Background work
Post by: devcom on January 05, 2009, 12:17:52 PM
Its should be a metronome, that used when you play guitar  ;)