I'm using a stopwatch to know how long some operations run for points (game) system.
I'm defining it like this:
Stopwatch sekunde = new Stopwatch();
long tocke;
long glavnetocke;
long cas;
tocke and glavnetocke are points.
Then in "construct" I need to do this:
sekunde.Start();
Thread.Sleep(10000);
sekunde.Stop();
If I don't do Thread sleep for 10000 it won't work.
Later in event handlers I use it like this:
sekunde.Start();
viewer.Clear();
viewer.DrawBody(body, 10.0, Brushes.Green, 10.0, Brushes.Green);
sekunde.Stop();
cas = (long)sekunde.Elapsed.TotalSeconds;
tocke = tocke + ((cas / 10));
if (tocke > 200)
{
glavnetocke = glavnetocke + 1;
tocke = 0;
}
viewer is to draw body of the person standing in front of a camera.
If I leave thread.sleep to 10000 it will work, otherwise it will not. But I need this to go away, because it stops the whole program. Even thou it happens only after I press a button in my form, I need to wait 10sec, before starting. Was thinking of just adding loading screen, but it doesn't work, as it freezes the whole program, so it doesn't show the loading gif.
EDIT:
well, as you can see that "tocke = tocke +((cas / 10));
tocke is always 0 if I remove thread.sleep or even lower the sleep number. Does stopwatch need time to initialize or something?
I want to get time of how long the operation runs to a long type variable so I can then use it for ingame points calculating. (cas = (long)sekunde.Elapsed.TotalSeconds;)
By casting TotalSeconds as a long you are chopping off the fraction part. I've redone your example using doubles and it seems to work for me:
Stopwatch sekunde = new Stopwatch();
long glavnetocke = 0;
double cas;
double tocke = 0;
sekunde.Start();
sekunde.Stop();
cas = sekunde.Elapsed.TotalSeconds;
tocke = tocke + ((cas / 10));
if (tocke > 200)
{
glavnetocke = glavnetocke + 1;
tocke = 0;
}
Result
cas = 0.0000015 (on my setup)
Related
I am working on voltmeter application, that draws voltage waveform. Hardware sends 1000 numbers (range 0 - 1023, always whole numbers) in string format per second through serial port.
public SerialPort serialPort = new SerialPort("COM3", 57600);
serialPort.Open();
String is converted into int and then drawn with DrawLine into PictureBox.
// variable declarations, all is int, runs in its own thread
while (blToMeasure) // true after clicking on button
{
iPrevY = iY;
iY = Int16.Parse(serialPort.ReadLine());
graphicsGraph.DrawLine(penBlack, iX, iPrevY, iX + 1, iY);
// only this thread is accessing PictureBox
iX++;
if (iX > picBoxGraph.Width)
{
graphicsGraph.Clear(SystemColors.Control);
iX = 0;
}
if (iY > picBoxGraph.Height)
{
}
}
Issue is that drawing lines itself is fast as it should be only for a couple of seconds, but gets gradually slower.
I tried Int.Parse, Int32.Parse and splitting thread function multiple ways using lock (graphicsGraph) (moving conditions with Clear into another thread) or using BlockingCollection<int> (moving DrawLine into another thread, away from Parse). Nothing seems to work and app still gets slower a couple of times after like a minute of running.
There isn't issue with hardware itself, checked with another software. Is this too fast for C#?
Solution:
I got the best results using Port.ReadTimeout = 1 and Port.DiscardInBuffer(). Also using Form.DoubleBuffered = true, but it doesn't make a huge difference in this particular case.
// constructor
Port.ReadTimeout = 1;
Form.DoubleBuffered = true;
Here is the loop itself:
btn.Click() // click to start measuring
{
Port.DiscardInBuffer();
blToMeasure = true;
}
while (blToMeasure) // true after clicking on button
{
iPrevY = iY;
try {
iY = Int16.Parse(serialPort.ReadLine());
}
catch
{
// exception logic
}
graphicsGraph.DrawLine(penBlack, iX, iPrevY, iX + 1, iY);
// only this thread is accessing PictureBox
iX++;
if (iX > picBoxGraph.Width)
{
graphicsGraph.Clear(SystemColors.Control);
iX = 0;
}
if (iY > picBoxGraph.Height)
{
}
}
When the app starts to read from the port, there is always accumulated data, because my hardware is sending numbers all the time, so I get rid of the buffer. Than the drawing of lines is not executed in differing spikes and the speed is constant. Analyzing the issue with Watch, I found out, that it occasionaly takes much longer to read this data and because of 1000 reads per second, it slows down. So to prevent slowing down, I used Port.ReadTimeout, that skips the read, if it takes too long.
The difference is visible, drawing no longer slows down and it keeps the same pace for minutes from what I've tried. I consider this sufficient solution for my issue, thank you!
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.
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'm having problems making smooth animations in GDI+. The problem as I understand it from Googling is that there is some kind of bug with the clock-ticks in .NET on a multi-core processor. Here's a simplified version of what I'm doing:
class Animation
{
System.Diagnostics.Stopwatch sw = new Stopwatch();
float AnimationTime = 1000; //time it takes the animation to complete
public bool IsComplete
{ get { return sw.ElapsedMilliseconds > AnimationTime; } }
public void StartAnimation()
{
sw.Reset();
sw.Start();
}
public void DoFrame()
{
float PercentComplete = (float)sw.ElapsedMilliseconds / AnimationTime;
//draw the animation based on PercentComplete
}
}
DoFrame() is called like this:
Animation.Start();
do
{
Animation.DoFrame();
Application.DoEvents();
} while (!Animation.IsComplete);
The problem is that the animation is very smooth for about 15 frames then it jerks, it actually goes backward (sw.ElapsedMilliseconds gives a lesser value than the previous query). It's very annoying and it's ruining my otherwise smooth animation that looks great even on a Core 2 Duo (despite Microsoft saying this is a multicore bug). I have an i7 and the animation is smooth except for 2-3 frames per second that look "jerky".
I understand that this is a known issue and Microsoft blames it on the processor, so my question is, does anyone know any kind of solution for this? I tried using a Kalman filter and it sort of works. I was hoping maybe there is an established "correct" solution for this?
Oh b.t.w. I tried using DateTime instead of Stopwatch and got the same results.
I also tried:
double PercentComplete = (double)sw.ElapsedTicks / (double)Stopwatch.Frequency * 1000 / AnimationTime
It gives me the same results.
It probably has to do with the way you call DoFrame(). Using the following windows forms / GDI+ based algorithm you should alway get very smooth animations:
const double desiredFps = 500.0;
long ticks1 = 0;
var interval = Stopwatch.Frequency / desiredFps;
while (true)
{
Application.DoEvents();
var ticks2 = Stopwatch.GetTimestamp();
if (ticks2 >= ticks1 + interval)
{
ticks1 = Stopwatch.GetTimestamp();
// do the drawing here
}
}
I'm making a TextBox control in XNA and do not have access to the GameTime class. Currently I am trying to simulate the blinking text cursor caret and have successfully done so using this code:
int deltaTickCount = Environment.TickCount - previousTickCount;
if (deltaTickCount < CursorBlinkRate && Selected)
{
spriteBatch.Draw(emptyPixel, new Rectangle(caretLocation, Rectangle.Y + 1, caretWidth, caretHeight), Color.Black);
}
else if (deltaTickCount > CursorBlinkRate * 2)
{
previousTickCount = Environment.TickCount;
}
However, I'm a bit wary of using Environment.TickCount. If the computer was running long enough, wouldn't the program eventually crash or produce unpredictable behavior when the tick count exceeded its integral size?
Does anyone know what Windows does? I imagine it would use the system clock. Would that be a more suitable solution? I imagine they used something like total milliseconds in to the second instead of the tick count, but I'm not sure.
Thanks for reading.
I generally use the system diagnostics timer in a lot of situations.
It's a pretty powerful tool which creates a timer for you with a lot of good controls.
using System.Diagnostics;
Stopwatch timer = new Stopwatch();
Then use inbuilt controls:
timer.Start();
if(timer.elapsedMilliseconds() > ...)
{ }
timer.Reset();
etc...
This would allow you to reset the timer?
When Evnironment.TickCount rolls over, deltaTickCount will end up being negative, so you know it has happened. The calculation then becomes:
if (deltaTickCount < 0)
deltaTickCount = int.MaxValue - previousTickCount + Environment.TickCount;
Without bothering with what would happen in the case of an integer overflow, simply change to:
int deltaTickCount =
Environment.TickCount > previousTickCount
? Environment.TickCount - previousTickCount
: CursorBlinkRate * 3;