Music player freeze a bit when pressing next button too fast - c#

Based on:
C# windows form & using WMPLib
The Problem:
when pressing next or prev button too fast, the apps will freeze a bit (uncontrollable).
The Code:
private void next_event()
{
_paused = false;
if (list[current_index].Rows.Count != 0 && _playing == true)
{
if (option.random.Checked == true)
{
nextRandom(1);
}
else if (option.order.Checked == true)
{
if (list[current_index].Rows.IndexOf(_musicData[_NowPlaying]) == list[current_index].Rows.Count - 1)
{
setNowPlaying((Guid)list[current_index].Rows[0].Cells["Key"].Value);
}
else
{
setNowPlaying((Guid)list[current_index].Rows[list[current_index].Rows.IndexOf(_musicData[_NowPlaying]) + 1].Cells["Key"].Value);
}
}
seek_bar.Value = 0;
play();
}
}
private void prev_event()
{
_paused = false;
if (list[current_index].Rows.Count != 0 && _playing == true)
{
if (option.random.Checked == true)
{
nextRandom(2);
}
else if (option.order.Checked == true)
{
if (list[current_index].CurrentRow.Index == 0)
{
setNowPlaying((Guid)list[current_index].Rows[list[current_index].Rows.Count - 1].Cells["Key"].Value);
}
else
{
setNowPlaying((Guid)list[current_index].Rows[list[current_index].Rows.IndexOf(_musicData[_NowPlaying]) - 1].Cells["Key"].Value);
}
}
seek_bar.Value = 0;
play();
}
}
private void play() // play
{
button3.Text = "Pause";
dmp_status.Text = "Playing...";
_paused = false;
if (list[current_index].Rows.Count != 0)
{
if (File.Exists(_musicData[_NowPlaying].Cells["FileLocation"].Value.ToString()))
{
if (_playing == true) wmp.controls.stop();
if(wmp != null) wmp.close();
wmp = new WMPLib.WindowsMediaPlayer();
wmp.PlayStateChange += new WMPLib._WMPOCXEvents_PlayStateChangeEventHandler(PlayStateChange);
seek_bar.Value = 0;
setNowPlayingLabel(_musicData[_NowPlaying]);
if (!_musicData.ContainsKey(_LastPlaying)) _LastPlaying = Guid.Empty;
setNowPlayingColor(_musicData[_LastPlaying],_musicData[_NowPlaying]);
//wmp.URL = list[current_index].CurrentRow.Cells["FileLocation"].Value.ToString();
wmp.URL = _musicData[_NowPlaying].Cells["FileLocation"].Value.ToString();
wmp.controls.play();
wmp.settings.rate = wmp_rate;
wmp.settings.volume = volume_pos;
if (_playing == false) _playing = true;
}
else
{
next_event();
}
}
}
The Question:
I have hard time figuring why they need a delay(freeze) before playing each music, this making a problem when user press next button consecutively.

I think it is due to reentry. Happened when subsequent events are fire while the first event hasn't complete. To prevent this:
// add this line to your class member
private Object syncRoot = new Object();
// add this block to your next_event() method
if (!Monitor.TryEnter(syncRoot)) return;
try {
// add your existing code here
}
finally {
Monitor.Exit(syncRoot);
}

Related

Prevent one from doing action if one is activated (C# UNITY)

Good Day, I just want to ask if how can I do these.
I need to prevent one action from doing something if the another action is activated and vice versa . Here's the code i have written so far.
if (hit == "spr_player")
{
betOnPlayer = true;
if (betOnBanker)
{
Debug.LogError("You already bet on the banker cannot bet on the player"); ;
}
else
{
if (betOnPlayer)
{
bet[0] = chip;
chips_bet[0].enabled = true;
Chips(chip, 0);
Debug.LogError("Betting on the player");
}
else
{
Debug.LogError("You can not bet on the Player");
}
}
}
else if (hit == "spr_banker")
{
if (betOnPlayer)
{
Debug.LogError("You already bet on the banker cannot bet on the player");
betOnBanker = true;
}
else
{
if (betOnBanker)
{
bet[4] = chip;
chips_bet[4].enabled = true;
Chips(chip, 4);
Debug.LogError("Betting on the banker");
}
else
{
Debug.LogError("You can not bet on the Banker");
}
}
}
But the problem here is that I couldn't get to switch it on off . Could someone point out what I am doing wrong.
I guess your program is that first click is select target, second click is bet.
And when you set the flag to someone, you should also unset another one.
if (hit == "spr_player")
{
if (betOnPlayer)
{
// bet on player
}
else
{
betOnPlayer = true;
betOnBanker = false;
}
}
else if (hit == "spr_banker")
{
if (betOnBanker)
{
// bet on banker
}
else
{
betOnPlayer = false;
betOnBanker = true;
}
}
Another answer:
string currentSelect = "";
void Update() {
if(YOUR_INPUT_EVENT) {
if (hit == "spr_player")
{
if (currentSelect == "Player")
{
// bet on player
}
else
{
currentSelect = "Player"
}
}
else if (hit == "spr_banker")
{
if (currentSelect == "Banker")
{
// bet on banker
}
else
{
currentSelect == "Banker"
}
}
}
}

Is it possible to have a while loop slowed?

Rewrite: I'm writing a program to get a better understanding of C# and taking user input in. Right now I'm using WFA in C# with a textbox where I put the text of what I want pasted/typed out. Then I have two other boxes that have an interval input and a amount input. Everything worked perfectly fine until I added the amount input, I've added a while loop to a timer that is used to type/paste the text. However, for some reason that I'm not sure of.. The program disregards any input for the interval.
I have it basically setup like this
private void timerPaste_Tick(object sender, EventArgs e)
{
interval = Int32.Parse(interNum.Text);
timerPaste.Interval = interval;
if (typeModebool == true && pasteModebool == false)
{
while (amount > 0) //Need to find a way to make GUI responsive during while loop.
{
SendKeys.Send(textBox1.Text);
SendKeys.Send("{Enter}");
amount--;
}
timerPaste.Enabled = false;
amount = Int32.Parse(amountSetBox.Text);
}
if (pasteModebool == true && typeModebool == false)
{
while (amount > 0) //Need to find a way to make GUI responsive during while loop.
{
Clipboard.SetText(textBox1.Text);
SendKeys.Send("^{c}");
SendKeys.Send("^{v}");
SendKeys.Send("{Enter}");
amount--;
}
timerPaste.Enabled = false;
amount = Int32.Parse(amountSetBox.Text);
}
}
something like that..?
timerPaste.Elapsed += OnTickEvent;
private async void OnTickEvent(Object source,EventArgs e)
{
interval = Int32.Parse(interNum.Text);
timerPaste.Interval = interval;
if (typeModebool == true && pasteModebool == false)
{
while (amount > 0) //Need to find a way to make GUI responsive during while loop.
{
SendKeys.Send(textBox1.Text);
SendKeys.Send("{Enter}");
amount--;
}
timerPaste.Enabled = false;
amount = Int32.Parse(amountSetBox.Text);
}
if (pasteModebool == true && typeModebool == false)
{
while (amount > 0) //Need to find a way to make GUI responsive during while loop.
{
Clipboard.SetText(textBox1.Text);
SendKeys.Send("^{c}");
SendKeys.Send("^{v}");
SendKeys.Send("{Enter}");
amount--;
}
timerPaste.Enabled = false;
amount = Int32.Parse(amountSetBox.Text);
}
}
I actually was able to fix this, the problem was that the while loop listened to the timer the first time, then after that just started going off on it's own. I switched it to a if, with an else statement and everything works as intended now.
int i = 0;
private void timerPaste_Tick(object sender, EventArgs e)
{
if (typeModebool == true && pasteModebool == false) //Check what mode is being used
{
if (i < amount) //If runs until i == amount
{
SendKeys.Send(textBox1.Text);
SendKeys.Send("{Enter}");
amount--;
}
else
{
timerPaste.Enabled = false;
}
}
if (pasteModebool == true && typeModebool == false)
{
if (i < amount)
{
Clipboard.SetText(textBox1.Text);
SendKeys.Send("^{c}");
SendKeys.Send("^{v}");
SendKeys.Send("{Enter}");
amount--;
}
else
{
timerPaste.Enabled = false;
}
}
}

RichTextBox select all text after Up- / Down-arrow

I have a RichTextBox for which I have created a "scroll through sent messages" feature. This means that if the user sends (by pressing enter) any messages (up to 20), the user can then scroll through them in order by pressing the up/down arrows on the keyboard. This part works as intended.
The issue is: I want to select all text in the RichTextBox after each arrow press.
Here is my code:
private void rtb_inputField_KeyDown(object sender, KeyEventArgs e) {
RichTextBox inputField = (RichTextBox)sender;
string userInput = inputField.Text.Trim();
string[] clientScriptString = userInput.Split(' ');
string modifiedInput = string.Empty;
string macroString = string.Empty;
//Other code...
if (e.KeyData == Keys.Enter) {
//Other code..
if ((client != null) && (client.Connected)) {
macroString = runInputThroughMacroDictionary(userInput);
sendInputToServer(macroString); //Sent message
}
addSentMessageToHistory(userInput); //Added sent message to history
e.Handled = true;
e.SuppressKeyPress = true;
hasUpBeenPressed = false;
}
if ((e.KeyData == Keys.Up) || (e.KeyData == Keys.Down)) {
scrollThroughSentMessages(e);
rtb_inputField.SelectAll();
}
}
private void scrollThroughSentMessages(KeyEventArgs e) {
if (sentMessageHistory.Count > 0) {
if (e.KeyData == Keys.Up) {
if (!hasUpBeenPressed) {
scrollThroughMsgHist = sentMessageHistory.Count - 1;
}
else {
scrollThroughMsgHist--;
if (scrollThroughMsgHist < 0) {
scrollThroughMsgHist = sentMessageHistory.Count - 1;
}
}
hasUpBeenPressed = true;
}
if ((e.KeyData == Keys.Down) && (hasUpBeenPressed)) {
scrollThroughMsgHist++;
if ((scrollThroughMsgHist >= 20) || (scrollThroughMsgHist > (sentMessageHistory.Count - 1))) {
scrollThroughMsgHist = 0;
}
}
rtb_inputField.Text = sentMessageHistory[scrollThroughMsgHist];
}
}
private void addSentMessageToHistory(string message) {
int currentAmountOfMessage = sentMessageHistory.Count;
if (!string.IsNullOrWhiteSpace(message)) {
if (currentAmountOfMessage == 0) {
sentMessageHistory.Add(message);
}
else {
if (sentMessageHistory[currentAmountOfMessage - 1] != message) {
if (currentAmountOfMessage == 20) {
sentMessageHistory.RemoveAt(0);
}
sentMessageHistory.Add(message);
}
}
}
}
The first method does a whole bunch of things. (I removed some of the irrelevant code.) It adds the last sent message to sentMessageHistory (which is a List) via the third method. It also listens for Up/Down, and calls upon the second method.
The second method "scrolls through" each of the entries in the sentMessageHistory -List, and writes it in the RichTextBox. All of this works fine.
What doesn't work is the rtb_inputField.SelectAll(); after the second method has run.
I found the solution. I added the following:
if ((e.KeyData == Keys.Up) || (e.KeyData == Keys.Down)) {
scrollThroughSentMessages(e);
e.Handled = true;
e.SuppressKeyPress = true;
rtb_inputField.SelectAll();
}
I don't know what e.Handled and e.SupressKeyPress does, but it works. So now my code successfully selects the text after "scrolling through history".

C# how to trigger an alert when all picturebox has a value

I'm creating a memory game for my schoolproject and i have a problem of triggering a messagebox when player won the game and displays a note "You hav matched all cards!". Does anyone have the solution.
One part of the code:
private void Card1_Click(object sender, EventArgs e)
{
Card1.Image = Properties.Resources.car1;
if(usedCard1 == null)
{
usedCard1 = Card1;
}
else if(usedCard1 != null && usedCard2 == null)
{
usedCard2 = Card1;
}
if(usedCard1 != null && usedCard2 != null)
{
if(usedCard1.Tag == usedCard2.Tag)
{
usedCard1 = null;
usedCard2 = null;
Card1.Enabled = false;
Dupcard1.Enabled = false;
points = Convert.ToInt32(ScoreCounter.Text);
points = points + 10;
ScoreCounter.Text = Convert.ToString(points);
}
else
{
points = Convert.ToInt32(ScoreCounter.Text);
points = points - 10;
ScoreCounter.Text = Convert.ToString(points);
timer4.Start();
}
}
}
private void Dupcard1_Click(object sender, EventArgs e)
{
Dupcard1.Image = Properties.Resources.car1;
if (usedCard1 == null)
{
usedCard1 = Dupcard1;
}
else if (usedCard1 != null && usedCard2 == null)
{
usedCard2 = Dupcard1;
}
if (usedCard1 != null && usedCard2 != null)
{
if (usedCard1.Tag == usedCard2.Tag)
{
usedCard1 = null;
usedCard2 = null;
Card1.Enabled = false;
Dupcard1.Enabled = false;
points = Convert.ToInt32(ScoreCounter.Text);
points = points + 10;
ScoreCounter.Text = Convert.ToString(points);
}
else
{
points = Convert.ToInt32(ScoreCounter.Text);
points = points - 10;
ScoreCounter.Text = Convert.ToString(points);
timer4.Start();
}
}
}
private void Win()
{
foreach(PictureBox picture in cardsHolder.Controls)
{
if(picture != null)
{
}
}
MessageBox.Show("You've matched all cards", "Congratulations");
Close();
}
PS: cardsHolder is the name of the panel, and Win is the method of triggering message when player wins the game.
I presume that you set the PictureBox.Image property to null if you don't show an image on a PictureBox. So simply check that property:
private void Win()
{
if (cardsHolder.Controls.OfType<PictureBox>().Any(pb => pb.Image == null))
return;
MessageBox.Show("You matched all the icons!", "Congratulations");
Close();
}
OfType<PictureBox> selects all PictureBoxes from the Controls collection and Any returns true if one of them has no Image.

Need help figuring out repeatable equals and addition operator events

I am building a UWP calculator app using the MVVM pattern and I have just about everything figured out except how to get the equals button to calculate repeatedly and have my operator buttons work correctly. I can do one or the other, but I can't figure out how to do both. The code below works for a repeatable equals button, but the plus operator will yield the wrong answer when adding multiple values.
If I take out the second switch statement and change the variables back to using one Output variable then I can get the plus operator to work, but the equals button will fail when it repeats.
I am sure it is just a matter of adding a nested if statement or the addition of a bool somewhere, but I'm stumped! Please help. I've removed the non essential buttons and operators. Any other helpful suggestions on my code would be appreciated too.
Thank you!
public class ComputareViewModel : ViewModelBase
{
#region Private Fields
private double resultNumber = 0;
private double xResultNumber;
private double yResultNumber;
private string _outputValue = "0";
bool isOperationPerformed = false;
bool EqualsRepeated = false;
public ComputareViewModel()
{
}
public string OutputValue
{
get
{
return _outputValue;
}
set
{
_outputValue = value;
OnPropertyChanged("OutputValue");
}
}
public void OnNumberBtnClick(object sender, RoutedEventArgs args)
{
if ((_outputValue) == "0" || (isOperationPerformed))
_outputValue = "";
isOperationPerformed = false;
Button numberBtnClick = (Button)sender;
if ((string)numberBtnClick.Content == ".")
{
if (!_outputValue.Contains("."))
{
OutputValue = OutputValue + numberBtnClick.Content;
}
}
else
{
OutputValue = OutputValue + numberBtnClick.Content;
}
}
public void OnOperatorBtnClick(object sender, RoutedEventArgs args)
{
Button operatorBtnClick = (Button)sender;
if(isOperationPerformed == false)
{
if (xResultNumber != 0)
{
OnEqualsBtnClick(this, new RoutedEventArgs());
operationPerformed = (string)operatorBtnClick.Content;
isOperationPerformed = true;
EqualsRepeated = false;
}
else
{
operationPerformed = (string)operatorBtnClick.Content;
xResultNumber = Double.Parse(OutputValue);
isOperationPerformed = true;
}
}
else
{
//Do nothing.
}
}
public void OnEqualsBtnClick(object sender, RoutedEventArgs args)
{
if (EqualsRepeated == false)
{
if (double.TryParse(OutputValue, out yResultNumber))
switch (operationPerformed)
{
case "+":
{
OutputValue = (xResultNumber + yResultNumber).ToString();
break;
}
}
isOperationPerformed = true;
EqualsRepeated = true;
}
else
{
// If equals has already been clicked
if (EqualsRepeated == true)
if (double.TryParse(OutputValue, out xResultNumber))
switch (operationPerformed)
{
case "+":
{
OutputValue = (xResultNumber + yResultNumber).ToString();
break;
}
}
}
isOperationPerformed = true;
}
}
There are some logical problems in your code. First, after OnEqualsBtnClick is called, isOperationPerformed is true, if you want to call the OnOperatorBtnClick, it will always go to the else part and do nothing. Second, if you repeat click euqal button, xResultNumber is not 0, if you want to call OnOperatorBtnClick, it will then call the OnEqualsBtnClick, but EqualsRepeated is true now, so you should change EqualsRepeated to false. At last, xResultNumber is the value of last calculation, you should set it to 0 in OnEqualsBtnClick method.
So you can change your code like this:
public void OnOperatorBtnClick(object sender, RoutedEventArgs args)
{
Button operatorBtnClick = (Button)sender;
EqualsRepeated = false;
if (isOperationPerformed == false)
{
if (xResultNumber != 0)
{
OnEqualsBtnClick(this, new RoutedEventArgs());
operationPerformed = (string)operatorBtnClick.Content;
isOperationPerformed = true;
EqualsRepeated = false;
}
else
{
operationPerformed = (string)operatorBtnClick.Content;
xResultNumber = Double.Parse(OutputValue);
isOperationPerformed = true;
}
}
else
{
//Do nothing.
}
}
public void OnEqualsBtnClick(object sender, RoutedEventArgs args)
{
if (EqualsRepeated == false)
{
if (double.TryParse(OutputValue, out yResultNumber))
switch (operationPerformed)
{
case "+":
{
OutputValue = (xResultNumber + yResultNumber).ToString();
break;
}
}
isOperationPerformed = true;
EqualsRepeated = true;
}
else
{
// If equals has already been clicked
if (EqualsRepeated == true)
if (double.TryParse(OutputValue, out xResultNumber))
switch (operationPerformed)
{
case "+":
{
OutputValue = (xResultNumber + yResultNumber).ToString();
break;
}
}
}
isOperationPerformed = false;
xResultNumber = 0;
}

Categories