Computer Hope
Software => Computer programming => Topic started by: devcom on January 02, 2009, 07:19:59 AM
-
Code:
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 ?
-
so you want it in Sub Play to repeat while ForNum is greater than 0.
how about you try this in the While condition
While Not ForNum = 0
Hope this helps
,Nick(macdad-)
-
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
-
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
-
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.
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...
-
thanks for dropping in
-
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
-
ok i've done this:
Dim PlayThread As New System.Threading.Thread(AddressOf Play)
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
-
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
-
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.
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
-
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:
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 ;)
-
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...
-
global variable ?? You mean what ?
And you know how to close this second thread ?
PS:
Button1 - Start
Button3 - Stop
Button2 - Exit
-
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.
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:
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.
-
but you mean in single thread ? like:
Sub Main()
'code
Do While(mterminatethread)
'thread code...
Loop
'code
End Sub
or multi:
Sub Main()
'code
Play()
End Sub
Sub Play()
Do While(mterminatethread)
'thread code...
Loop
End Sub
and there is no command like Form_OnExit
or sth like that ??
-
YAY ! ;D Got this done allready ;D
Found this on internet:
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 ::)
-
lol, that's the method I just described ;D
-
lol, didnt know you are talking about that ::)
-
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.
-
Its should be a metronome, that used when you play guitar ;)