I'm very new to c# and coding in general and am having some problems implementing a timer in a for loop. Basically, the bit of code below is trying to create a number representative of trash output by an island at set intervals, with each output weighted based on island population to be a bit less predictable. it then adds the generated trash figure to a total. The problem I'm having is that the way tutorials use the Timer class means creating an 'Intervaltimer_Elapsed(object sender, ElapsedEventArgs e)' function outside of Main() and I can't work out how to then add whatever is generated by this back to the weights[] array in the Main(). All I really want to do is as soon as the compiler goes into the for loop, tell it to wait 'x' ticks, then continue. Thread.Sleep isn't an option because this is to go in unity, so would interrupt other things. apologies if the code below is a bit gory!
{
class Program
{
public static double trashperstan8 = 600 * 3.21;
public static int population = 1000;
public static double trashperpersperday = 1;
public static double interval = 60;
public static double intperday = 1440 / interval;
public static double trashperint = population * trashperpersperday * (interval / 1440);
public static int weightnum = population / 200;
static void Main(string[] args)
{
double Trashlevel = new double();
double stand8sfilled = new double();
Timer intervaltimer = new Timer((interval / 30) * 1000);
Console.WriteLine(weightnum);
for (int inti = 0; inti < intperday; inti++)
{
/* at this point, I want to basically tell the code: each time you go
through the for loop, wait for x number of ticks then do the method */
Console.WriteLine(inti);
double[] weights = new double[weightnum];
Random rand = new Random();
for (int i = 0; i < weightnum; i++)
{
double weightcontrib = rand.NextDouble();
weights[i] = weightcontrib;
Console.WriteLine("{0}: {1}", Array.IndexOf(weights, weightcontrib), weightcontrib);
}
double finalweight = 2 * (weights.Sum() / weightnum);
Console.WriteLine("final weight " + finalweight);
double weightedtpi = trashperint * finalweight;
Trashlevel = Trashlevel + weightedtpi;
stand8sfilled = stand8sfilled + (weightedtpi / trashperstan8);
}
Console.WriteLine("trash level " + Trashlevel);
Console.WriteLine("stand8s filled " + stand8sfilled);
}
private static void Intervaltimer_Elapsed(object sender, ElapsedEventArgs e)
{
}
}
}
All I really want to do is as soon as the compiler goes into the for loop, tell it to wait 'x' ticks, then continue. Thread.Sleep isn't an option because this is to go in unity, so would interrupt other things.
Solution 1: Don't write a loop at all. The timer already is logically a loop.
Write a method that is the "body" of the "loop".
"Starting the loop" is activating a timer where the body method is the event handler and the timer fires every n milliseconds
"Terminating the loop" is deactivating the timer.
Solution 2: Write a loop, don't use a timer.
Make the method async and then await Task.Delay(whatever); to asynchronously wait for your delay. Your method will suspend when it hits the await, and resume at some point after the delay task is complete.
The latter is probably the better solution in that the code more closely resembles your description of it.
I don't know enough about Unity to say which is the better solution in their framework.
Related
I'm trying to plot the function y = x ^ 2 at a certain interval using the Graphics, but I can't. When I write start + = 1/10 (to increase the number of points) knocks out the error that the index went beyond the array, and in this case what it is now, the graph does not look as it should. Maybe someone can help me build this chart using Graphics.
P.S: yes I know I can use Chart, but the task is to do it through Graphics.
using System.Drawing;
using System.Windows.Forms;
namespace FormsForProgrammin
{
public partial class Form15 : Form
{
PointF[] p = new PointF[10];
int count = 0;
public Form15()
{
InitializeComponent();
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form15_Paint);
Calc();
}
private void Calc()
{
float start = float.Parse(textBox1.Text);
while(start<= float.Parse(textBox2.Text))
{
float res = start * start;
p[count] = new PointF(start, res);
count += 1;
start += 1;
}
}
private void Form15_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.TranslateTransform(150, 150);
e.Graphics.ScaleTransform(1, 0.25F);
e.Graphics.DrawLines(Pens.Blue, p);
}
}
}
you have an array of 10 points, and you are indexing them with the count variable. you have a couple of problems in that code:
you never reset count
you set start to the textBox1 value, and increment it by 1 untill it is over the textBox2 value. but this gap may be bigger than the number of points you have in the array
to solve for 1 you can either reset count once the loop is done, or simply define count in the Calc method itself (the latter would be the better option, since count is only relevant to the Calc method)
to solve for 2 you would need to calculate a step amount: the difference between values divided by the number of points,
use this step amount to make sure that the loop doesn't run more times than the numbers of points you have
I'm creating a console game as simple as "I generate a random number, find it", but with many options.
My current code (without what I want here) is availlable on GitHub: https://github.com/crakmaniaque/trouvezmoi
What I want is to create a version of my game which will be timed, so the computer generates numbers, the user finds it, it generates a new one and the player have 90 seconds to find a max lot of random numbers. I can code this easily.
What I will need help is to stop the game (a thread) after 90 seconds and retrieve the number of answers founded from the thread. The Console.Title should also show time remaining. The attempt I've tried works, but the thread is not interrupted if console is asking for number input (Console.ReadLine()). But the timer is for the entire process, not only user input.
private static void timerb()
{
int t = 90;
for (int i = 0; i < 90; i++)
{
Console.Title = t + " seconds remaining";
Thread.Sleep(1000);
t--;
}
}
private static void cGame()
{
Thread t = new Thread(timerb);
t.Start();
while (t.IsAlive)
{
bool good = false;
int rnd = new Random().Next(0,10); // 0 and 10 are sample
while (!good)
{
try
{
Console.Write("Enter a number between x and y >");
int i = int.Parse(Console.ReadLine());
if (i == rnd)
{
good = true;
}
}
catch (FormatException)
{
Console.WriteLine("Invalid answer.");
}
}
}
}
I don't know much about threading and at that point I'm stuck.
Can someone help me with my problem? I'm using .NET 2.0.
Perhaps you are looking for a timer? You could register an event, that would fire after 90 seconds, that would run while the loop is happening. The documentation can be found here: Timer class MSDN documentation.
I believe the usage would be:
Timer timer = new Timer { Interval = new Timespan (0,1,30);
timer.elapsed += //function to fire to kill the app or the game
You'd need to make each console read with a timeout equal to the amount of time left in the game. That solves that issue.
Then, you need a way to signal the timerb thread to shut down when the main game loop has ended. I think the simplest way would be to end the game loop when the remaining time is <= zero. Alternatively, you could make timerb singnal the main thread to shut down when t == 0. Inter-thread communication is always complicated and error-prone, though.
You can signal the timerb thread to shut down by setting a volatile bool shutdown to true and by making timerb poll that variable and shut itself down.
I am trying to figure out how to count 10 times each second and display it.
I have an int called countpoints which is what the user starts with points. Lets say 800.
I would like to drop 10 points each second but showing each point falling instead of every 10 points like my script below does.
here is how I have done so far:
if(miliseconds <= 0){
if(seconds <= 0){
minutes--;
seconds = 59;
}
else if(seconds >= 0){
seconds--;
countpoints = countpoints-10;
}
miliseconds = 100;
}
miliseconds -= Time.deltaTime * 100;
This runs in void update and here countpoints falls by 10 each second. but i would like to be able to show the numbers drop down like a stopwatch each second. How do i do that?
Any help is appreciated and thanks in advance :-)
You should use coroutine for that calculation instead of in Update(). It can be very easy with the coroutine. You just need to start croutine and then wait for 0.1 seconds and decrease counterpoints by 1. Again call that coroutine inside that to keep it running. Just add condition whenever you want to keep on calling it.
private int countpoints=800;
private float t=0.1f;
private int noOfSeconds=90;
private int min;
private int sec;
private int temp=0;
void Start ()
{
StartCoroutine(StartTimer());
}
IEnumerator StartTimer ()
{
yield return new WaitForSeconds(t);
countpoints--;
temp++;
if(temp==10)
{
temp=0;
noOfSeconds--;
}
min = noOfSeconds/60;
sec = noOfSeconds%60;
if(noOfSeconds>0)
{
StartCoroutine(StartTimer());
}
}
void OnGUI ()
{
GUI.Label(new Rect(100f,100f,100f,50f),countpoints.ToString());
GUI.Label(new Rect(100f,160f,100f,50f),"Time : "+min.ToString("00")+":"+sec.ToString("00"));
}
You could just do it in the Update method and decrement the points once every 100ms, you need to take care of not rounding things up or down as the error would be systematic and you'll get choppy results.
Using coroutines won't work as expected as the interval is not guaranteed.
private float _milliseconds = 0;
private int points = 800;
void Update()
{
_milliseconds += Time.delta * 1000;
if( _milliseconds > 100 )
{
points--;
//add updating GUI code here for points
_milliseconds -= 100;
}
}
You won't get choppy decrements as the _milliseconds are decremented by 100, so even if there are differences in the duration of the frames in the long run you'll get a proper handling.
One problem with the script is if frames take a lot more than 100ms consistenly , but if it takes that long you probably have bigger problems:D
I am wondering how I can make a decreasing counter to replace a timer, as in the timer would start at 3, and decrease every second, until reaching zero, where it would preform an action. Any Help?
// Change Image from "Hut" to Mole \\
private void ChangeImage()
{
Image newImage = HoleImage();
molePopup = MoleImage();
int numCol = Convert.ToInt32(NumberOfColumns);
//Random Number - Col
Random randomColumns = new Random();
int ranCol = randomColumns.Next(1, numCol);
//Random Number - Row
Random randomRow = new Random();
int ranRow = randomRow.Next(1, NumberofRows);
string Moleimage = TUtils.GetIniFileString(Moleini, "ImagePath", "PictureFile", Root + "mole2.png");
//Populate Grid with Mole at Random Times \\
Grid.SetRow(molePopup, ranRow);
Grid.SetColumn(molePopup, ranCol);
grid_Main.Children.Add(molePopup);
molePopup.MouseUp += new MouseButtonEventHandler((o, e) =>
{
MolePoints++;
grid_Main.Children.Remove(molePopup);
});
}
I may be unclear, but as long as you only have the one thread in the program (and nothing going on otherwise), you'd use something like this:
for(int i = 3; i > 0; i--)
{
Thread.Sleep(1000);
}
doWhatever();
For each iteration of the loop, you "sleep" the thread 1000 milliseconds, or 1 second. To do this, you will need to include System.Threading with using System.Threading. If you're doing something in the background, use alternate methods instead of Sleep, since it locks the thread execution for the duration specified.
EDIT:
This is the MSDN documentation for Thread.Sleep() method. Seems to be very similar to what you want to do, if I take your meaning correctly.
Use DispatcherTimer
Set the interval property to 1000 (= 1 second)
Create a variable that represents your countdown timer
Create a tick event in which you check if your countdown variable is zero. If it is zero => stop timer and perform action. If not => decrease variable
Start the timer
I need to make a console application that uses Kinect, with Kinect SDK and c#. Since it's a console application, I've found polling to be the best way to retrieve the frames I need to process. I'll need to retrieve frames from the depth camera and the rgb camera, do some processing on then in separate threads (one for the depth image and one for the rgb image), and give an output to the user for each of the two processed frames. The way I've been thinking about doing this is the following:
1 - create 2 threads, the first is on the method that polls the rgb camera and do the processing, the second is on the method that polls the depth camera and do the processing
2 - Start the threads
3 - enter a while some stop condition loop
4 - check separately if each thread is alive, if not, create them again and start them again
I've made a test program that follows those steps and it works, but I'm not sure it's the best way of doing it. My test program is
class Program
{
private static ClassExecutioner Executioner;
private static Class1 Cls;
static void Main(string[] args)
{
Executioner = new ClassExecutioner();
Cls = new Class1();
Thread fThread = new Thread(new ThreadStart(processA));
Thread sThread = new Thread(new ThreadStart(processB));
fThread.Start();
sThread.Start();
while (true)
{
if (!fThread.IsAlive)
{
fThread = new Thread(new ThreadStart(processA));
fThread.Start();
}
if (!sThread.IsAlive)
{
sThread = new Thread(new ThreadStart(processB));
sThread.Start();
}
}
}
static void processA()
{
String frameA = Cls.pollA();
Executioner.CallA(frameA);
}
static void processB()
{
String frameB = Cls.pollB();
Executioner.CallB(frameB);
}
}
Class 1 methods represent the polling of the cameras on kinect
class Class1
{
private int a;
private int b;
public Class1()
{
a = 0;
b = 0;
}
public String pollA()
{
String frame = "this is " + a % 100;
a++;
return frame;
}
public String pollB()
{
String frame = "I am " + b % 100;
b++;
return frame;
}
}
Executioner represents the methods that process the frames obtained from Kinect
class ClassExecutioner
{
public ClassExecutioner()
{
}
public void CallA(String frameA)
{
Random rand = new Random();
int time = rand.Next() % 1000000000;
//'processing' - wait some time
for (int i = 0; i < time; i++)
{
}
// finishes the processing of the 'frame' from stream A
Console.WriteLine(frameA);
}
public void CallB(String frameB)
{
Random rand = new Random();
int time = rand.Next() % 1000000000;
// 'processing' - wait some time
for (int i = 0; i < time; i++)
{
}
// finishes the processing of the 'frame' from stream B
Console.WriteLine(frameB);
}
}
The program is very simple but ilustrates well what I want to do with the Kinect streams. The problem is, I'm not sure this is the best way of doing it or even if this is gonna work at all on a practical, Kinect application. Keep in mind that, for now, each processing (depth and rgb) doesn't need information from the other.
Thanks in advance!
It might be cool to look into the ReactiveExtensions framework. It deals with async event streams very cleanly.
You can write LINQ against the data sources and do very interesting composable operations.
http://msdn.microsoft.com/en-us/data/gg577609.aspx
You basically would have two IEnumerable sequences (the things that loop infinitely) that yield out the frame at the given interval. You can then "query" these sequences using Rx. RX handles all the complicated threading issues for you and makes your consumer code clean and simple.
To be clear, you don't want to be creating new threads each time. You can create two infinite enumerables that each run on their own thread and yield out the result on each iteration. That way they don't even "die"