A timer suitable for webgame "ticks" - c#

im trying to create a timer to "tick" and created this timer with a little google help.
It works perfectly in console, but when i added it in a website, it seems my computer is running at full capasity, and the site is loading slowly and not function properly.
Can i use this or do i need to start over?
namespace ticket
{
class Program
{
public static int counttick = 0;
public static int ticks = 0;
static void LoopingFunction()
{
while (counttick <= 20)
{
int dwStartTime = System.Environment.TickCount;
while (true)
{
if (System.Environment.TickCount - dwStartTime > 1000) break; //1000 milliseconds
}
counttick++;
if (counttick == 20)
{
ticks++;
counttick = 0;
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
Label2.Text = "Ticks: " + Convert.ToString(ticks);
LoopingFunction();
}
}
}`

Remove:
while (true)
{
if (System.Environment.TickCount - dwStartTime > 1000) break; //1000 milliseconds
}
And use:
System.Threading.Sleep(1000);

Try System.Threading.Timer class.

In web applications i don't recommend using static variables, because you really never know when you IIS will recycle the app pool and you static varitable will become 0. rather you should try something to persistence storage. and use to Try System.Threading.Timer class to update the value in may be a Database table or some file.
Regards.

I'll just give another approach. I needed a similar tick loop that runs at about 25 frames per second. I have a class called ApplicationLoop which, when constructed starts a thread. That thread is my application loop. (Hence the obvious class name.)
So I have a few constants, to determine my frame rate, and a frame-skip fallback value. Basically, when a task takes more time than 40ms (1000 / 25 = 40), I loop through all the tasks again to "catch-up". But I only do this a number of times.
private const int MAX_FRAMESKIP = 5;
private const int UPDATE_SKIP_TICKS = 1000 / UPDATE_TICKS_PER_SECOND;
private const int UPDATE_TICKS_PER_SECOND = 25;
My thread function:
private void UpdateLoop()
{
ulong ticks = 0UL;
_isRunning = true;
var next = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
while (_isRunning)
{
var now = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
int loops = 0;
while ((now > next) && _isRunning && (loops < MAX_FRAMESKIP))
{
ProcessTasks(ticks);
next += UPDATE_SKIP_TICKS;
loops++;
ticks++;
}
AccurateSleep(1);
}
}
My class contains a Subscribe() function which takes a delegate. I store that callback into a List and the ProcessTasks() function calls each subscribed function.
You can replace the AccurateSleep() function with a simple Thread.Sleep(1) call, but be aware that the default time-slice for a sleep is about 15ms.
[DllImport("winmm.dll")]
private static extern uint timeBeginPeriod(uint period);
[DllImport("winmm.dll")]
private static extern uint timeEndPeriod(uint period);
private static void AccurateSleep(int sleep)
{
timeBeginPeriod(1);
Thread.Sleep(sleep);
timeEndPeriod(1);
}

Related

Updating multiple line in a console application

I've been struggling with Parallel.For and local variable. I'm trying to update percentages in a console app from a parallel for. I add page in multiple document and I would like an update on the percentage for each document.
Here's my attempt so far :
I'm taking the number of the line with Console.CursorTop, and I want to pass it to a method who's gonna override the line.
Loop from Program.cs
Parallel.For(0, generationFile.nbOfFile, optionsParallel,
i =>
{
string fileName = $"{tmpDirectoryPath}/{i + 1}_{guid}.pdf";
AddPage(fileName, generationFile, i);
});
The AddPage method
private static void AddPage(string fileName, GenerationFile generationFile, int i)
{
var cursorPosition = Console.CursorTop;
//Ajout des pages
for (int j = 0; j < generationFile.SizeMaxFile; j++)
{
Page page = Page.Create(outDoc, size);
AddText(outDoc, page, font, 14, i, fileName, j, generationFile.SizeMaxFile);
for (int k = 0; k < 292; k++)
{
AddImage(outDoc, page, 30, 30);
}
outDoc.Pages.Add(page);
ConsoleManager.UpdateConsole(i, j, cursorPosition, generationFile);
}
}
The UpdateConsole method
public static void UpdateConsole(int fileNumber, double progression, int cursorPosition, GenerationFile generationFile)
{
progression = (progression / 100) * generationFile.ArchiveESC;
Console.ForegroundColor = ConsoleColor.White;
Console.SetCursorPosition(0, cursorPosition);
Console.WriteLine($"\rFichier n°{fileNumber + 1}/{generationFile.SizeMaxFile} en cours de création : {progression}% ", Console.ForegroundColor);
}
I think everything works fine, except for the cursorPosition who take one value at the beginning and never change, so the same line is updated. I understand that there is something to do with local and/or shared variable, but I'm fairly new in parallel processing so even with the other threads on this topic and the MSDN, I don't understand what to do.
The way I prefer to handle progress reporting is to have all worker threads report to a shared progress field, and have a separate timer that reads this fields and reports the progress to the user. This lets me control how often progress is reported, regardless of how fast items are processed. I also want an abstraction layer that allows different ways to report progress. After all, the same method might be used from console, the UI, or not at all.
For example something like this:
public interface IMyProgress
{
void Increment(int incrementValue);
}
public sealed class MyProgress : IMyProgress, IDisposable
{
private readonly int totalItems;
private readonly Timer myTimer;
private volatile int progress;
private int lastUpdatedProgress;
public MyProgress(TimeSpan progressFrequency, int totalItems)
{
this.totalItems = totalItems;
myTimer = new Timer(progressFrequency.TotalMilliseconds);
myTimer.Elapsed += OnElapsed;
myTimer.Start();
}
private void OnElapsed(object sender, ElapsedEventArgs e)
{
var currentProgress = progress;
if (lastUpdatedProgress != currentProgress)
{
lastUpdatedProgress = currentProgress;
var percent = currentProgress * 100 / (double)totalItems;
Console.Write($"\rWork progress: {percent}%");
}
}
public void Increment(int incrementValue) => Interlocked.Add(ref progress, incrementValue);
public void Dispose() => myTimer?.Dispose();
}
This can be called from a parallel method like:
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var myWorkItems = Enumerable.Range(1, 10000).ToList();
using var progress = new MyProgress(TimeSpan.FromSeconds(1), myWorkItems.Count);
DoProcessing(myWorkItems, progress);
}
private static void DoProcessing(IEnumerable<int> items, IMyProgress progress)
{
Parallel.ForEach(items, item =>
{
Thread.Sleep(20);
progress.Increment(1);
});
}
I would be a bit careful when using carriage returns. In my experience console applications tend to be used by other programs as much as by humans, and then it is likely that the output will be redirected to a file, and that does not support carriage returns. So I would try to make the output look good.
I would avoid trying to move the cursor around. I have tried that, but the result was unsatisfactory, YMMV.

c# Call a method every x seconds but only a certain amount of times

Im looking to call the same method every x seconds in my c# console app, but I also want to only call this method a certain number of times (say 5).
I need each method to run after each other (cant have them over lapping)
My biggest issue is the console app closing before being completed
The current code I have works but is kinda messy (the while loop)
static void Main(string[] args)
{
for (int t = 0; t < 3; t++)
{
InitTimer(t);
}
}
public static void InitTimer(int t)
{
Console.WriteLine("Init" + t);
int x = 0;
var timer = new System.Threading.Timer(
e => x = MyMethod(x),
null,
TimeSpan.Zero,
//delay between seconds
TimeSpan.FromSeconds(5));
//number of times called
while (x < 5)
{
}
timer.Dispose();
}
public static int MyMethod(int x)
{
Console.WriteLine("Test" + x);
//call post method
x += 1;
return x;
}
}
Is there a neater way to create the same functionality ?

Multiple Threads but not locking still gives correct result

I imagined the result would be a negative value, due to not locking and multiple threads sharing the same object. I have tested this many times with release and debug version, every time the result is correct. Why is it still correct?
Code :
static BankAccount ThisbankAccount = new BankAccount(10000);
public static void WithdrawMoney()
{
for(int i = 0; i < 1000; i++)
ThisbankAccount.WithdrawMoney(25);
}
static void Main(string[] args)
{
Thread client1 = new Thread(WithdrawMoney);
Thread client2 = new Thread(WithdrawMoney);
Thread client3 = new Thread(WithdrawMoney);
client1.Start();
client2.Start();
client3.Start();
client3.Join();
Console.WriteLine( ThisbankAccount.Balance);
Console.ReadLine();
}
}
public class BankAccount
{
object Acctlocker = new object();
public BankAccount(int initialAmount)
{
m_balance = initialAmount;
}
public void WithdrawMoney(int amnt)
{
// lock(Acctlocker)
// {
if (m_balance - amnt >= 0)
{
m_balance -= amnt;
}
// }
}
public int Balance
{
get
{
return m_balance;
}
}
private int m_balance;
}
Just because something works now doesn't mean it is guaranteed to work. Race conditions are hard to trigger and might take years to surface. And when they surface, they can be very hard to track down and diagnose.
To see your problem in action, change this code:
if (m_balance - amnt >= 0)
{
m_balance -= amnt;
}
to:
if (m_balance - amnt >= 0)
{
Thread.Sleep(10);
m_balance -= amnt;
}
That introduces a slow enough code path to highlight the problem really easily.
The reason you aren't spotting it with your current code is that the operations you are doing (subtraction and comparisons) are very fast. So the window for the race condition is very small - and you are lucky enough for it not to occur. But, over unlimited time, it definitely will occur.

Why does the QueuePerformanceCounter behave odd?

Good day fellow developers,
I'm trying to create a Timing class in C# which can output the amount of time it takes to execute specific lines code. Here is the class that I developed so far (it is using the QueryPerformanceCounter):
class Timing
{
private long start;
private long stop;
private long frequency;
Decimal multiplier = new Decimal(1.0e9);
// Importing important DLL's that will be used
[DllImport("KERNEL32")]
private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
[DllImport("Kernel32.dll")]
private static extern bool QueryPerformanceFrequency(out long lpFrequency);
// Timing constructor
public Timing()
{
if (QueryPerformanceFrequency(out frequency) == false)
{
// Frequency not supported
throw new Win32Exception();
}
}
// Method for starting the counter
public void Start()
{
QueryPerformanceCounter(out start);
}
// Method for stopping the counter
public void Stop()
{
QueryPerformanceCounter(out stop);
}
// Returns the average time between iterations in nanoseconds
public double Duration(int iterations)
{
return ((((double)(stop - start) * (double)multiplier) / (double)frequency) / iterations);
}
// Get the elapsed time between the start and the stop function in nanoseconds
public double getElapsedTime()
{
return (((double)(stop - start) * (double)multiplier) / (double)frequency);
}
}
I wanted to perform a test to see if my Timing class would print out the same amount of time when executing the same line of code five times in a row:
static void Main(string[] args)
{
runCollectionTest(1000);
runCollectionTest(1000);
runCollectionTest(1000);
runCollectionTest(1000);
runCollectionTest(1000);
while (true) ;
}
public static void runCollectionTest(int iterations)
{
Timing timer = new Timing();
timer.Start();
ArrayList list = new ArrayList();
for (int i = 0; i < iterations; i++)
{
list.Add(i);
}
timer.Stop();
Console.WriteLine("Time elapsed: " + timer.getElapsedTime() / 1000000 + " milliseconds");
}
Here is the output of the code:
Time elapsed: 0,24631157341192 milliseconds
Time elapsed: 0,0486376114202896 milliseconds
Time elapsed: 0,0620241099763327 milliseconds
Time elapsed: 0,0589005936465893 milliseconds
Time elapsed: 0,088350890469884 milliseconds
I have no idea how the first time elapse and the second one can differ that much compared to the other results.

How to make a count timer C#

I'm trying to create a timer in c# for an online game. All i really want is a timer that counts 60 seconds and then restarts. And let it go forever, then add a point for every time it resets...
What i've done so far is:
DateTime dateTime = DateTime.Now;
int sec = dateTime.Second;
if(sec = 1)
{
// stuff
}
The if does not loop, how do I do that? or anyone have a better idea? I'd really like one where i can change the seconds.
I think System.Threading.Timer might be useful, just set a callback that triggers after 60 seconds.
i found something related to my question and edited to what i wanted. it does what I want it to do, but does it create overflow or not, that im not sure of. Does anyone have a better idea of doing this?
using System;
namespace ticket
{
class Program
{
public static int x = 0;
static void LoopingFunction()
{
while (x <= 20)
{
int dwStartTime = System.Environment.TickCount;
while (true)
{
if (System.Environment.TickCount - dwStartTime > 100) break; //100 milliseconds
}
Console.WriteLine(x);
x++;
if (x == 20)
{
///add "stuff"
Console.WriteLine("Test");
x = 0;
}
}
}
static void Main()
{
LoopingFunction();
Console.Read();
}
}
}

Categories