I currently have a program which plays a set of videos from a playlist then displays a set of images once the videos are done playing. I am currently using the PlayStateChange event to count each time a video is ending but this results in the images displaying at the beginning of the last video and not at the end. I need a way to trigger the images when the playlist is completely done playing. I even tried delaying the code but that causes my display image method to act screwy. Here is a code sample, not that it is really needed to answer my question.
private void player_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if (!currSess.playOne)
{
Console.WriteLine(player.playState);
if (e.newState == 8 | e.newState == 9)
{
if (e.newState == 8)
{
currSess.playQueue++;
Console.WriteLine(currSess.playQueue);
}
}
if (currSess.playQueue+1 > player.currentPlaylist.count -1)
{
// await Task.Delay(1000);
displayImgs();
player.PlayStateChange -= foo;
currSess.playQueue = 0;
}
}
}
Fixed by adding another if statement, since if the last video is done playing it will assume the ready state and stop there:
if (currSess.playQueue+1 > player.currentPlaylist.count -1)
{
if (e.newState == 10)
{
// await Task.Delay(1000);
displayImgs();
currSess._timer.start();
Console.WriteLine(currSess._timer);
AllowControls(true);
allowItems();
player.PlayStateChange -= foo;
currSess.playQueue = 0;
}
}
Related
I have an audio player that loads a configuration file with a list of files to be played at certain intervals. Like 5 files should be looped between 09:30 and 11:30 - it is an application for libraries where they need the background music.
When im outside of an interval, i loop through all my time intervals (there might be 2 hours before next interval starts) and then if i find that nothing is to be played right now - i sleep for a second and then try again.
I have a problem where i get a stack overflow after around 3-4 hours of checking for these time intervals (often at nights, because the clients are on, but no music should be playing at night).
private void PlayNextFile()
{
Application.DoEvents();
if (currentState == PlayerState.Started)
{
//if we find the next slide then play it
AudioSlide slideToPlay = FindNextSlide();
if(slideToPlay != null)
{
PlaySlide(slideToPlay);
}
else
{
MedianLog.Log.Instance.LogDebug("Did not find a slide to play now, will check again in a second");
System.Threading.Thread.Sleep(1000);
PlayNextFile();
}
}
}
Any idea on how to get around this exception?
You just filling up your stack with not controlled recursive calls.
A while loop would be a better solution.
Something like that should do it correctly:
private async void PlayNextFile()
{
while (true)
{
if (currentState == PlayerState.Started)
{
//if we find the next slide then play it
AudioSlide slideToPlay = FindNextSlide();
if (slideToPlay != null)
{
PlaySlide(slideToPlay);
return;
}
MedianLog.Log.Instance.LogDebug("Did not find a slide to play now, will check again in a second");
await Task.Delay(1000);
}
else
{
return;
}
}
}
The problem is with the button:contains('Deal') selector, the button containing deal does exist on the page and Watin can find it without problems when running in main thread.
// Add bet, deal cards and wait for animation
private void dealCards()
{
// Start the game if chip exists
if (browser.Image(Find.BySrc(chipURL)).Exists)
{
browser.Image(Find.BySrc(chipURL)).Click();
// This is where the thread stops
browser.Button(Find.BySelector("button:contains('Deal')")).Click();
Thread.Sleep(dealCardsAnimationTime);
if (Convert.ToInt32(browser.Span(Find.ByClass("player-points")).Text) == 21)
{
consoleTextBox.AppendText("You won by blackjack.");
gameOver = true;
}
return;
}
}
Update:
Browser is a Internet Explore window that I interact with using WatiN, other than the UI changes, the problem seems to be that WatiN can't find the button.
However it's still somewhat related to multithreading, as the same code works fine without multithreading and the element that it's searching for does exist.
Update 2: Changed title and description of problem as the old one appeared to be unrelated.
Context ( in case it's necessary )
// When bet button is clicked
private void button2_Click(object sender, EventArgs e)
{
blackjackThread = new Thread(blackjackGame);
if (dealInProgress == false)
{
blackjackThread.Start();
// blackjackGame();
}
}
// Blackjack deal handler
private void blackjackGame()
{
consoleTextBox.AppendText("\r\n");
resetVariables();
dealCards();
if (gameOver == true)
{
checkResult();
dealInProgress = false;
blackjackThread.Abort();
return;
}
checkCards();
logPoints();
while (gameOver == false)
{
botAction();
}
checkResult();
dealInProgress = false;
blackjackThread.Abort();
return;
}
After being out of scripting for ages I have decided to learn a programming language and I have gone for C#. I'm getting along pretty well but now for the first time I seem to have been faced with a problem that I have not been able to solve with google.
I am making a simulated aircraft system as a learning exercise and I want to invoke a loop when an option is selected from a drop down combobox.
I have a combobox/list with three options which simulates the starter switch, the values are (0)Off, (1)On, (2)Ignition Only . In the real aeroplane, when 'On' is selected the switch locks in place for 10 seconds and then releases. So what I am trying to achieve is :
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
if (starterRight.SelectedIndex == 0)
{
//Starter is off
eng2Start.Value = 0;
}
if (starterRight.SelectedIndex == 1)
{
//starter is on
//Start Timer
eng2Start.Value = 1;
if (eng2Tourqe >= 6000)
{
//open fuel valve
// set Hot Start counter to 0
}
else
{
//ensure fuel valve stays closed
// set Hot Start counter to x+1
}
// End of Timer
// set selected index back to 0
(starterRight.SelectedIndex == 0)
}
}
I have googled and googled and the more I read the more I am getting lost in this. I have found answers containing a mass of code which I am not able to fully decipher just yet.
Is it possible to do what I want to do?
Thanks in advance for your time.
You can Add Timer to your Form and Set the Interval property to 10000(10 seconds).
from code:
if (starterRight.SelectedIndex == 1)
{
//starter is on
//Start Timer
timer1.Enabled=true;
}
//in timer tick Event write the following:
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Enabled=false;
//Statements to start aircraft
}
You could achieve this by setting it to true (or selected, or whatever you want) sleeping for 10 seconds, like this:
Thread.Sleep(10000) ;
and then set it back to false (or unselect, or whatever you want)
Another way to go would be to start a background thread that will sleep for ten seconds, and then call a method that will "unset" the button, this way, not blocking the GUI ...
Or depending on what you're using, I could probably come up with other options, but i'll take it you're trying to learn the basics atm ... :)
See this one msdn timer
And you can use Threed.Sleep(10000);
I think this should works. I didn't compile it, but with this you lock the swtich, do your stuff checking a timer that when arrives to 10 sec, re-enable your switch.
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
if (starterRight.SelectedIndex == 0)
{
//Starter is off
eng2Start.Value = 0;
}
if (starterRight.SelectedIndex == 1)
{
//starter is on
starterRight.enable = false;
StopWatch sw = new StopWatch();
sw.Start();
eng2Start.Value = 1;
if (eng2Tourqe >= 6000)
{
//open fuel valve
// set Hot Start counter to 0
}
else
{
//ensure fuel valve stays closed
// set Hot Start counter to x+1
}
if (sw.ElapsedMilliseconds <= 10000)
{
do
{
//Dummy Loop
}
while (sw.ElapsedMilliseconds > 10000)
sw.Stop();
}
else
{
// set selected index back to 0
sw.Stop();
starterRight.Enabled = true;
(starterRight.SelectedIndex == 0)
}
}
}
You can use a Timer and the Tick event. Disable your switch, and when the Timer tick, Enabled it.
Timer timerSwitchOn;
public SomeConstructor()
{
timerSwitchOn = new Timer(){Interval = 10*1000}; // 10 seconds
timerSwitchOn.Tick += new EventHandler(timerSwitchOn_Tick);
}
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
if (starterRight.SelectedIndex == 1)
{
//starter is on
starterRight.Enabled = false;
timerSwitchOn.Start();
}
}
void timerSwitchOn_Tick(object sender, EventArgs e)
{
timerSwitchOn.Stop();
starterRight.Enabled = true;
// set selected index back to 0
starterRight.SelectedIndex = 0;
}
In my initial question I said I had wanted to invoke a loop, I meant a timer but it seems that you all figured that out.
Thank you for the rapid answers, I am going to get stuck into them this weekend and see if I can solve my problem.
For my programming class we are required to make a memory match game. When the player clicks on a panel an image is displayed. The player clicks on two panels, if the images match they are removed, if they are different they are turned face down.
The problem I am having with this is that only the image from the first panel gets displayed, even though I am using the same line of code to display the images from both panels, and use Thread.Sleep to pause the program after the second tile has been picked. I don't understand why this is happening, any help would be appreciated.
private void tile_Click(object sender, EventArgs e)
{
string tileName = (sender as Panel).Name;
tileNum = Convert.ToInt16(tileName.Substring(5)) - 1;
//figure out if tile is locked
if (panelArray[tileNum].isLocked == false)
{
pickNum++;
//although the following line of code is used to display the picture that is stored in the tile array
//what is happening is that it will only display the picture of the first tile that has been picked.
//when a second tile is picked my program seems to ignore this line completely, any ideas?
panelArray[tileNum].thisPanel.BackgroundImage = tiles[tileNum].tileImage;
if (pickNum == 1)
{
pick1 = tileNum;
panelArray[tileNum].isLocked = true;
}
else
{
pick2 = tileNum;
UpdateGameState();
}
}
}
private void UpdateGameState()
{
Thread.Sleep(1500);
if (tiles[pick1].tag == tiles[pick2].tag)//compares tags to see if they match.
{
RemoveTiles();
}
else
{
ResetTiles();
}
pickNum = 0;
guess += 1;
guessDisplay.Text = Convert.ToString(guess);
if (correct == 8)
{
CalculateScore();
}
}
try this:
(sender as Panel).BackgroundImage = tiles[tileNum].tileImage;
you have to be sure that your tile_Click method is associated to both panel...
i've a problem with windows phone shakegesture library.
I build an application which its shaking the sound will go out and its work nicely but strange bug make me confused. I've two page of it. This is my seperated code :
void Instance_ShakeGesture1(object sender, ShakeGestureEventArgs e)
{
Stream stream = TitleContainer.OpenStream("Sounds/C.wav");
effect = SoundEffect.FromStream(stream);
effectInstance = effect.CreateInstance();
if (effectInstance.State != SoundState.Playing || effectInstance == null)
{
FrameworkDispatcher.Update();
effectInstance.Play();
}
else if (effectInstance.State == SoundState.Playing || effectInstance != null)
{
effectInstance.Stop();
}
}
void Instance_ShakeGesture2(object sender, ShakeGestureEventArgs e)
{
Stream stream = TitleContainer.OpenStream("Sounds/D.wav");
effect = SoundEffect.FromStream(stream);
effectInstance = effect.CreateInstance();
FrameworkDispatcher.Update();
if (effectInstance.State == SoundState.Stopped || effectInstance == null)
{
effectInstance.Play();
}
else if (effectInstance.State == SoundState.Playing || effectInstance != null)
{
effectInstance.Stop();
}
}
Instance_ShakeGesture1 is my procedure to play a music when its shaking in Page 1 and Instance_ShakeGesture2 in Page 2.
Strange bug was come when its shaking, if i shake page 1 Instance_ShakeGesture1 will executed after that I try move to page 2 and i shake it will execute Instance_ShakeGesture1 first and than Instance_ShakeGesture2.
The Problem was come same when i try to shake Page 2 first and than Page 1, Instance_ShakeGesture2 will execute first and Instance_ShakeGesture2 in the second.
I know this bug when i use breakpoint.
Anyone know how to solve this problem? Thanks before :)
Possibly the event Instance_ShakeGesture1 is still active when you navigate to the second page. try
Instance.ShakeEvent -= new EventHandler(Instance_ShakeGesture1);
inside the Instance_ShakeGesture1 method.
try this, it worked for me,
protected override void OnBackKeyPress(CancelEventArgs e)
{
e.Cancel = false;
ShakeGesturesHelper.Instance.ShakeGesture -= new EventHandler<ShakeGestureEventArgs>(Instance_ShakeGesture1);
}
Because you should delete the events when you leaving first page. So you can clean hakeGestureEventArgs when back key button is pressed.
Okay my bad. Didn't know that you needed it to work multiple times.
Try this and let me know if it works good:
Write the same line of code that you've added, inside the OnNavigatedFrom method and delete it from your current method('Instance_ShakeGesture2')