replacement for thread.sleep - c#

I'm trying to make a Tamagochi but I've ran into a problem. I have a Progressbar with a max value of 300. Every 5-8 seconds the Progressbar empties a bit. Once it gets below 250 you're allowed to sleep.
Here is the code i have so far:
private void BtnSleep_Click(object sender, EventArgs e)
{
if (PgbSleep.Value <= 250)
{
int temp = PgbSleep.Maximum - PgbSleep.Value;
if (temp + PgbSleep.Value >= 300)
{
Timer2.Stop();
Thread.Sleep(20000);
PgbSleep.Value = 300;
Timer2.Start();
}
}
else
{
MessageBox.Show("Your pokemon is not tired enough to sleep! try playing with it");
}
}
I'm trying to find a replacement for the
Thread.Sleep(20000);
But dont know what to use. Any help would be much appreciated!
The
Thread.Sleep(20000);
Is supposed to be a cooldown, once its completed the user is allowed to sleep again if the requirements are met.

Try using a timer:
Timer sleepTimer = new Timer(20000); //Creates a timer for sleeping
public MyClass()
{
sleepTimer.Elapsed += new EventHandler((s, e) => WakeUp());
}
private void BtnSleep_Click(object sender, EventArgs e)
{
if (PgbSleep.Value <= 250)
{
int temp = PgbSleep.Maximum - PgbSleep.Value;
if (temp + PgbSleep.Value >= 300)
{
Timer2.Stop();
sleepTimer.Start();
}
}
else
{
MessageBox.Show("Your pokemon is not tired enough to sleep! try playing with it");
}
}
private void WakeUp()
{
PgbSleep.Value = 300;
Timer2.Start();
}

Related

How to iterate through a list of object on timer_tick event?

I have a list
static List<Participants> soop = ParticipantRepository.GetAllParticipants();
It has some 800 items. Then there's a label and a timer. At timer_tick, I want to display one of the items randomly. Here's the code for that event
private void timer1_Tick(object sender, EventArgs e) {
foreach (var participants in soop)
{
a = participants.RollNumber;
label1.Text = a;
break;
}
counter++;
if (counter == 200) {
timer1.Stop();
pictureBox5.Visible = false;
counter = 0;
}
}
I have not been able to achieve the random functionality so far because only one RollNumber is being displayed and then the timer takes its time and runs out. What am I doing wrong?
I would suggest using the random class.
Random randomGen = new Random();
private void timer1_Tick(object sender, EventArgs e)
{
var i = randomGen.Next(0, soop.Count);
label1.Text = soop[i].RollNumber;
counter++;
if (counter == 200)
{
timer1.Stop();
pictureBox5.Visible = false;
counter = 0;
}
}
At each tick the timer1_Tick is called, so your foreach loop starts back from the beginning and you end up displaying the first item every time. Instead, you can store the index of the last item you displayed. You already have counter so let's use it:
private void timer1_Tick(object sender, EventArgs e)
{
label1.Text = soop[counter % soop.Count].RollNumber;
counter++;
if (counter == 200) {
timer1.Stop();
pictureBox5.Visible = false;
counter = 0;
}
}

Updating progressbar through backgroundworker in method

My programm (in C# using Windows Forms) is reading and parsing large amounts of Data and I'm using a Backgroundworker which calls those global methods (reading and parsing). I'd like to keep the user updated on how long it's going to take, so the Backgroundworker is supposed to display what action its doing and has a progressbar that should fill for every individual action too.
Unfortunately, I can't get it to work, as the progressbar just doesn't update at all and just stays empty.
Here is what I have so far:
private void InitializeBackgroundWorker()
{
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
}
private void buttonParse_Click(object sender, EventArgs e)
{
DescriptionLabel.Visible = true;
progressBar1.Visible = true;
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
Methods.ParsePerfusionData(backgroundWorker1); //Also tried using 'worker' here, but didnt work either
}
And in the method it looks like that:
public static void ParsePerfusionData(BackgroundWorker worker)
{
for (int i = 2; i < Globals.DataList.Count; i++)
{
worker.ReportProgress(i / amount * 100);
rest of the code etc.
}
}
Can I not use a backgroundworker in a global method like that? Thanks in advance!
When i < amount then i / amount * 100 = 0 * 100 = 0.
Simply use i * 100 / amount instead.
Also make sure backgroundWorker1.WorkerReportsProgress = true
You can only report progress between distinct operations. That means either:
using a very modern class that supports this level of reporting. Such a classs might not exist for your case.
reverse engineering parts of the code down to the loop you want to make reporting on. Usually the loop that itterates over files or the like.
GUI updates must be contained to RunWorkerCompelted and ProgressReport events. And depending on how often updates happen, ProgressReport may have to be kept to only updating a progress bar.
Here some old code I wrote with BackgroundWorker wich should get you started:
#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
if (!bgwPrim.IsBusy)
{
//Prepare ProgressBar and Textbox
int temp = (int)nudPrim.Value;
pgbPrim.Maximum = temp;
tbPrim.Text = "";
//Start processing
bgwPrim.RunWorkerAsync(temp);
}
}
private void btnPrimCancel_Click(object sender, EventArgs e)
{
if (bgwPrim.IsBusy)
{
bgwPrim.CancelAsync();
}
}
private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
int highestToCheck = (int)e.Argument;
//Get a reference to the BackgroundWorker running this code
//for Progress Updates and Cancelation checking
BackgroundWorker thisWorker = (BackgroundWorker)sender;
//Create the list that stores the results and is returned by DoWork
List<int> Primes = new List<int>();
//Check all uneven numbers between 1 and whatever the user choose as upper limit
for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
{
//Report progress
thisWorker.ReportProgress(PrimeCandidate);
bool isNoPrime = false;
//Check if the Cancelation was requested during the last loop
if (thisWorker.CancellationPending)
{
//Tell the Backgroundworker you are canceling and exit the for-loop
e.Cancel = true;
break;
}
//Determin if this is a Prime Number
for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
{
if (PrimeCandidate % j == 0)
isNoPrime = true;
}
if (!isNoPrime)
Primes.Add(PrimeCandidate);
}
//Tell the progress bar you are finished
thisWorker.ReportProgress(highestToCheck);
//Save Return Value
e.Result = Primes.ToArray();
}
private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pgbPrim.Value = e.ProgressPercentage;
}
private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
pgbPrim.Value = pgbPrim.Maximum;
this.Refresh();
if (!e.Cancelled && e.Error == null)
{
//Show the Result
int[] Primes = (int[])e.Result;
StringBuilder sbOutput = new StringBuilder();
foreach (int Prim in Primes)
{
sbOutput.Append(Prim.ToString() + Environment.NewLine);
}
tbPrim.Text = sbOutput.ToString();
}
else
{
tbPrim.Text = "Operation canceled by user or Exception";
}
}
#endregion

Cross-thread operation not valid because of button.performClick()

Hi I am working on a TABU Search Algorithm and I need to access many functions to make it readable and easy I have used buttons and button.performClick();
Can someone let me know what I am doing wrong and how I can solve this issue?
Thank you
struct DataParameter
{
public int Process;
public int Delay;
}
private DataParameter _inputparameter;
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
lblBackGroundWorker.Text = string.Format("Processing...{0}%", e.ProgressPercentage);
progressBar1.Update();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
int process = ((DataParameter)e.Argument).Process;
int delay = ((DataParameter)e.Argument).Delay;
int index = 1;
try
{
//progressBar1.Value = 0;
//progressBar1.Update();
progressBar = 1;
//this.tmrTimeAndDate.Start();
Reset_Clear_For_New_Timetable();
sw_WhileLoop = Stopwatch.StartNew();
while (whileLoop > 0)
{
if (!backgroundWorker.CancellationPending)
{
backgroundWorker.ReportProgress(index++ * 100 / process, string.Format("Processing...{0}%", progressBar));
Thread.Sleep(delay); // used to simulate length of operation
if (whileLoop == 99)
{
Console.WriteLine("initial"); // initial
cmd_Start_Scheduling.PerformClick(); // create timetable
Get_Timetable_Send_To_Initial_DataTable(); // get timetable to the initial table
Get_Timetable_Send_To_Optimal_DataTable(); // get timetable to the optimal table
Calculate_Energy_High_Score_Initial();//calculate high score of initial solution
Calculate_Energy_High_Score_Optimal();//calculate high score of optimal solution
Reset_Clear_For_New_Timetable();
}
else
{
Console.WriteLine("not initial");// not initial
cmd_Start_Scheduling.PerformClick(); // create timetable
Fill_New_Solution();
Compare_Solution_Keep_The_Best();
Reset_Clear_For_New_Timetable();
}
whileLoop = whileLoop - 1;
progressBar = progressBar + 1;
}
}
sw_WhileLoop.Stop();
MessageBox.Show("Time taken: " + sw_WhileLoop.Elapsed.TotalSeconds.ToString() + " seconds \n Scheduling ended on step 7 because there was no Sup Class Left.");
MessageBox.Show("Done");
TimetableOutputQuestion TimetableOutputQuestionOpen = new TimetableOutputQuestion();
this.Hide();
TimetableOutputQuestionOpen.Show();
progressBar = 1;
whileLoop = 99;
}
catch (Exception ex)
{
backgroundWorker.CancelAsync();
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Timetable Scheduling Process Has Been Completed", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void CmdStartScheduling_Click(object sender, EventArgs e)
{
if (!backgroundWorker.IsBusy)
{
_inputparameter.Delay = 100;
_inputparameter.Process = 1200;
backgroundWorker.RunWorkerAsync(_inputparameter);
}
}
private void cmdStopScheduling_Click(object sender, EventArgs e)
{
if (backgroundWorker.IsBusy)
{
backgroundWorker.CancelAsync();
}
}
Add This code to the end in your while loop (inside the loop)
DateTime timeout = DateTime.Now.AddMilliseconds(50);
while (DateTime.Now < timeout) Application.doEvents;
it should do the trick.
Good luck

How to wait until a timer stops

I need to wait the next line to be waiting until a timer finishes.
public void animation(){
timer1.start();
labelStatus.Visibility=true;
}
I want the labelStatus to be visible after the timer1 finished.
private void timer1_Tick(object sender, EventArgs e)
{
int fromX = lblMove.Location.X;
int fromY = lblMove.Location.Y;
if (fromY > moveToY)
{
Y = Y - 5;
lblMove.Location = new Point(fromX, Y);
}
else if (fromY < moveToY)
{
Y = Y + 5;
lblMove.Location = new Point(fromX, Y);
}
else
{
timer1.Stop();
}
}
thanks in advance.
Simplest solution I can think of is this
public void animation(){
timer1.start();
labelStatus.Visibility=false;
}
private void timer1_Tick(object sender, EventArgs e)
{
[...]
else if (fromY < moveToY)
{
Y = Y + 5;
lblMove.Location = new Point(fromX, Y);
}
else
{
timer1.Stop();
labelStatus.Visibility = true;
}
}
This way when you stop the timer you make the label visible. There are many other ways of doing this but this should be simple.
Second method.
Apparently Timer doesn't have a "OnStopped" event to hook to (unless you want to try with dispose). However a Timer has a System.Timer.Timer.Enabled flag for telling you that it's running.
It's not a clean solution, but you could create a new Thread and Poll "timer.Enabled" until it turns false.

C#, Constantly monitor battery level

I am designing a program that depends on monitoring the battery level of the computer.
This is the C# code I am using:
PowerStatus pw = SystemInformation.PowerStatus;
if (pw.BatteryLifeRemaining >= 75)
{
//Do stuff here
}
My failed attempt of the while statement, it uses all the CPU which is undesirable.
int i = 1;
while (i == 1)
{
if (pw.BatteryLifeRemaining >= 75)
{
//Do stuff here
}
}
How do I monitor this constantly with an infinite loop so that when it reaches 75% it will execute some code.
Try Timer:
public class Monitoring
{
System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
public Monitoring()
{
timer1.Interval = 1000; //Period of Tick
timer1.Tick += timer1_Tick;
}
private void timer1_Tick(object sender, EventArgs e)
{
CheckBatteryStatus();
}
private void CheckBatteryStatus()
{
PowerStatus pw = SystemInformation.PowerStatus;
if (pw.BatteryLifeRemaining >= 75)
{
//Do stuff here
}
}
}
UPDATE:
There is another way to do your task complete. You can use SystemEvents.PowerModeChanged.
Call it and wait for changes, monitor the changes occured then do your stuff.
static void SystemEvents_PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs e)
{
if (e.Mode == Microsoft.Win32.PowerModes.StatusChange)
{
if (pw.BatteryLifeRemaining >= 75)
{
//Do stuff here
}
}
}
While loop will cause your UI to response poor and the application will get crashed. You can solve this by using many ways. Please check out the below code snippet will help your needs.
public delegate void DoAsync();
private void button1_Click(object sender, EventArgs e)
{
DoAsync async = new DoAsync(GetBatteryDetails);
async.BeginInvoke(null, null);
}
public void GetBatteryDetails()
{
int i = 0;
PowerStatus ps = SystemInformation.PowerStatus;
while (true)
{
if (this.InvokeRequired)
this.Invoke(new Action(() => this.Text = ps.BatteryLifePercent.ToString() + i.ToString()));
else
this.Text = ps.BatteryLifePercent.ToString() + i.ToString();
i++;
}
}
BatteryChargeStatus.Text = SystemInformation.PowerStatus.BatteryChargeStatus.ToString();
BatteryFullLifetime.Text = SystemInformation.PowerStatus.BatteryFullLifetime.ToString();
BatteryLifePercent.Text = SystemInformation.PowerStatus.BatteryLifePercent.ToString();
BatteryLifeRemaining.Text = SystemInformation.PowerStatus.BatteryLifeRemaining.ToString();
PowerLineStatus.Text = SystemInformation.PowerStatus.PowerLineStatus.ToString();
If you want to perform some operation just convert these string values into the integer.

Categories