Pause, enter a command and resume console app - c#

I have a C# console app that do some work and keeps printing every 4 seconds market data.
Is there a way to be able to enter a command within the refresh rate to change some parameters and make the app continue following the new input?

Yes you could. Let's define 2 flows, one for main running and second for waiting new read line. Using a global variable to change through the processing between 2 flows, which is:
Running(): Print a line from HyperParam then sleeping 4 seconds
Task.Run(() => ...): Starting a infinity loop for reading a new HyperParam. Each loop will go sleeping 100 ms. That mean the user has at least 40 chances within 4 seconds to change the value.
static string HyperParam = "A";
static void Running()
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine($"Running with: {HyperParam}");
Thread.Sleep(4000);
}
}
static void Main(string[] args)
{
Task.Run(() =>
{
while (true)
{
HyperParam = Console.ReadLine();
Thread.Sleep(100);
}
});
Running();
}
Result:

Related

C# Thread and lock

I test simple code
static Thread _readThread = null;
static private Object thisLock = new Object();
static int a = 1;
private static void ReadComPort()
{
lock (thisLock)
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine(Thread.CurrentThread.Name + " " + a++.ToString());
Thread.Sleep(1000);
}
}
}
static void Main(string[] args)
{
for (int i = 0; i < 3; i++)
{
_readThread = new Thread(new ThreadStart(ReadComPort));
_readThread.IsBackground = true;
_readThread.Name = i.ToString();
_readThread.Start();
//Thread.Sleep(50);
}
Console.WriteLine("End");
Console.ReadKey();
}
but why is the sequence of execution and the launching of threads chaotic:
0,2,1 Why?
Console output:
0 1
End
0 2
0 3
2 4
2 5
2 6
1 7
1 8
1 9
Because you can't expect threads to start or run in a specific order. The OS schedules threads the way it wants to. Sometimes it puts a thread on hold, executes another one, before coming back to the original one.
Here you see that the threads start almost at the same time. Obviously (from the output) thread 0 wins it to the first lock. Then, by pure chance, thread 2 gets by the lock earlier than thread 1. This could have gone entirely different since the threads are created shortly after each other. As said: there is no guarantee.
Lock does not guarantee the order : Does lock() guarantee acquired in order requested?
Also, in your code, you should wait your threads to finish at the end of your for loop in order to not have "end" at the beginning - if you press a key, you will exit while your thread are still running, and you may have unexpected behaviour.
Read the C# reference carefully.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement
There, you cannot find anything about the order of threads entering the lock block.

How to execute threads every min correctly?

This question is in two parts.
I have a console application that gets info from several servers and saves this info to a DB. In order to enabel that this executes simultaniously i have used threads. I am trying to make this execution automatic every minute.
Searching stackoverflow i found that this could work:
var timer = new System.Threading.Timer((e) =>
{
var models = ServerHandler.GetServerModels();
foreach (var m in models)
{
ServerHandler.MakeThreads(m);
}
Console.WriteLine("Running...");
Console.WriteLine("Press 'X' to exit or close the window, i : " + i);
i++;
}, null, 0, TimeSpan.FromMinutes(1).Seconds);
However this is not working as anticipated, it only executes once. If i change to for example this:
TimeSpan.FromMinutes(0.5).Seconds
Or:
TimeSpan.FromSeconds(30).Seconds
Then it works.
What am I doing wrong?
Second part of this question:
When this actually works as I showed above something else happens.
The process runs continuously and after 474 threads it crashes and says that the system is out of memory.
I tried using thread sleep for this but when i do that it stops executing after it has runed once.
Including this if it might help:
public static void MakeThreads(ServerModel model)
{
Thread thread = new Thread(() => SaveServerInfo(model));
thread.Start();
//Thread.Sleep(1);
//thread.Join();
}
How can I make this work?
In your first problem using the .Seconds will only return the seconds value, but you are defining the minutes value as .5, so seconds will always be zero.
If you want to return the seconds you need to use TotalSeconds
TimeSpan.FromMinutes(0.5).TotalSeconds
and in the timespan you are using you are supposed to define the milliseconds. So you're getting a huge number of threads because its running every 30 millseconds instead of every 30000 milliseconds.
So use
TimeSpan.FromMinutes(0.5).TotalMilliseconds
or what i always find easier
(int)(1000 * 60 * 0.5) // Then you just replace the 0.5 with the number of seconds.
Basically a timer does exactly what it's supposed to do: run your code every 0.5 seconds. :) An in your case, that's a problem...
(Please check for syntax errors etc, I'm writing this in notepad)
Long solution
Your problem seems to be that you don't control your threads. Here's how I'd solve it: (This long solution shows how it more or less works)
while (true)
{
// we want to run it again in 0.5 seconds.
DateTime start = DateTime.UtcNow.AddSeconds(0.5);
Thread[] threads = new Thread[models.Count];
for (int i=0; i<models.Count; ++i)
{
threads[i] = new Thread((a) => SaveServerInfo((ServerModel)a));
threads[i].Start(models[i]);
}
for (int i=0; i<models.Count; ++i)
{
threads[i].Join();
}
DateTime current = DateTime.UtcNow;
if (current < start)
{
Thread.Sleep(start.Subtract(current));
}
}
Short solution
However, this might give you issues as well: you might spawn too many threads. This can be solved with a mechanism called thread pooling. As it turns out, there's a simple way to solve this:
static void DoStuff(string s)
{
// change to a value > 0.5 as well to ensure everything works
Thread.Sleep(TimeSpan.FromSeconds(0.1));
Console.WriteLine(s);
}
static void Handle(List<string> models)
{
while (true)
{
// we want to run it again in 0.5 seconds.
DateTime start = DateTime.UtcNow.AddSeconds(0.5);
Parallel.ForEach(models, (a) => DoStuff(a));
DateTime current = DateTime.UtcNow;
if (current < start)
{
Thread.Sleep(start.Subtract(current));
}
}
}
static void Main(string[] args)
{
List<string> models = new List<string>();
for (int i = 0; i < 10; ++i)
{
models.Add(i.ToString());
}
Handle(models);
}

Prevent my console application from closing after a .Net.Timer starts

So I have this simple code:
static void Main(string[] args)
{
var timer = new Timer(0.5 * 60 * 1000); // 0.5 minutes times 60 seconds times 1000 miliseconds
timer.Elapsed += new System.Timers.ElapsedEventHandler(Start);
timer.AutoReset = true;
timer.Start();
}
Which starts a timer that starts the whole program logic. Problem is, the console application closes and nothing is done. How do I prevent this? I know that if I do something like while(true) it works, but that does not seem like an elegant/proper solution.
Maybe try
Console.Read();
At the end of the code
Thanks to this your console window will not be closed as long as a user will not press a key.
The last answer is 7 years old. In the meantime, methods from System.Threading like Timer, Sleep, ...
should not be used anymore. They carry the risk of deadlocks, and I have to warn against their use especially in ASP.NET Core.
There are several things to consider:
No program runs forever. What happens when the program should be closed (by a shutdown or a signal)?
The termination must be implemented in your program logic. Many async .NET Core methods supports a CancellationToken as a parameter.
There are 2 approaches to create an "endless" program:
Worker Services in .NET Core are the common approach today to write programs that should run permanently as a service. They can be registered as Windows Service.
More Infos on learn.microsoft.com and devblogs.microsoft.com if you want to register your service as a "real" service.
If you need a "real" console application that performs tasks in the foreground, this can be done with the following sample code:
using System;
using System.Threading.Tasks;
using System.Threading;
namespace DemoApp
{
internal class Program
{
private static int _isRunning = 0;
private static async Task Main(string[] args)
{
// No program can run infinitely. We always have to provide a mechanism for termination.
var tcs = new CancellationTokenSource();
var periodTimeSpan = TimeSpan.FromSeconds(10);
// This mechanism is CTRL+C, so we catch this.
Console.CancelKeyPress += (sender, e) =>
{
tcs.Cancel();
e.Cancel = true;
};
try
{
// No endless loop. We are checking for a cancellation request!
while (!tcs.IsCancellationRequested)
{
// Perform your work.
var task1 = Run(tcs.Token);
var task2 = Task.Delay(periodTimeSpan, tcs.Token);
// If the execution time of Run is greater than periodTimeSpan, we will wait. Depends on your needs.
await Task.WhenAll(task1, task2);
}
}
catch (TaskCanceledException)
{
Console.WriteLine("User canceled your app.");
}
}
private static async Task Run(CancellationToken token)
{
// Should never occur if you use WhenAll()
if (Interlocked.Exchange(ref _isRunning, 1) == 0)
{
// Perform your work.
_isRunning = 0;
}
}
}
}
Add a Console.ReadKey(); this will allow you to close the console window by pressing any key.
static void Main(string[] args)
{
var timer = new Timer(0.5 * 60 * 1000); // 0.5 minutes times 60 seconds times 1000 miliseconds
timer.Elapsed += new System.Timers.ElapsedEventHandler(Start);
timer.AutoReset = true;
timer.Start();
Console.ReadKey();
}
If you want to just run a timer and wait, then Console.Read() is your friend.
The reason why your code is terminating is because the function initializes the timer, starts it and then ... hits the end of the Main function. As a result, the function exits.
The current code doesn't do anything useful (besides starting a timer which is ignored).
If you want to see your timer in action, do some other work after you start the timer. Then, stop the timer after an interval and print it/evaluate it how you deem fit. (The timer doesn't run on the main thread, whereas something like Console.Read() will be on the main thread and thus, block the thread until you have input)
Your console application does not end because the timer starts. It ends because the program reaches the end of the Main() method.
Whatever action you take to prevent the program from exiting Main() will help. While many proposed solutions actually do this. I wanted to highlight the fact that it's not the timer causing the issue.

stopwatch c# behave differently in different threads?

I'm currently using a stopwatch as a global timer. I have main thread running, another thread, and an event method.
The main thread launches the other thread and the event method is triggered by events. Both methods will call the stopwatch and get its time. The thing is, the times are not consistent:
from main thread:
START REC AT 9282
STOp REC AT 19290
from another thread:
audio 1
audio 304
audio 354
audio 404
audio 444
audio 494
audio 544
audio 594
from event method:
video 4
video 5
video 29
video 61
video 97
video 129
video 161
I don't get why if i start my rec at 9282, the other two functions that call the stopwatch will have timers that start at zero? Is this a thread related issue? How can i fix this? Thanks
UPDATE:*********
when i save my frames i changed to:
long a = relogio.EllapseMilliseconds
i print out this value and its ok, as expected. but when i print the value stored in the lists, they come as starting from the beggining. strange huh?
SORRY FOR ALL THE TROUBLE, I PRINTED IT WITHOUT THE STARTING TIME,THATS WHY THEY ALL SEEMED TO START FROM ZERO! MANY THANKS AND SORRY!
main thread
private void Start_Recording_Click(object sender, RoutedEventArgs e)
{
rec_starting_time = relogio.ElapsedMilliseconds;
Console.WriteLine("START REC AT " + rec_starting_time);
write_stream.enableRecording();
Thread a = new Thread(scheduleAudioVideoFramePicks);
a.Start();
scheduleAudioVideoFramePicks - this thread just counts the time, so i know when to stop
//while....
if (rec_starting_time + time_Actual > rec_starting_time+recording_time * 1000)//1000 - 1s = 1000ms
{
totalRecordingTimeElapsed = true;
write_stream.disableRecording();
Console.WriteLine("STOp REC AT " + relogio.ElapsedMilliseconds);
}
//end while
lock (list_audio)
{
int b = 0;
//print time of frames gathered
foreach(AudioFrame item in list_audio){
Console.WriteLine("audio " + (item.getTime() - rec_starting_time));
}
lock (list_video)
{
}
foreach (VideoFrame item in list_video)
{
Console.WriteLine("video " + (item.getTime() - rec_starting_time));
}
}
the another thread, where i get the time
if (write_stream.isRecording())
{
list_audio.Enqueue(new AudioFrame(relogio.ElapsedMilliseconds, audioBuffer));
}
event method
if (write_stream.isRecording())
{
list_video.Add(new VideoFrame(relogio.ElapsedMilliseconds, this.colorPixels));
}~
i dont know if this is relevant, but i start my stopwatch like this
public MainWindow()
{
InitializeComponent();
//some code
this.relogio = new Stopwatch();
relogio.Start();
}
Stopwatch is not threadsafe, particularly for 32-bit programs.
It uses the Windows API call QueryPerformanceCounter() to update a private long field. On 32-bit systems you could get a "torn read" when one thread reads the long value while another thread is updating it.
To fix that, you'd have to put a lock around access to the Stopwatch.
Also note that one some older systems there were bugs where inconsistent values could be returned from different threads calling QueryPerformanceCounter(). From the documentation:
On a multiprocessor computer, it should not matter which processor is called. However, you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL). To specify processor affinity for a thread, use the SetThreadAffinityMask function.
I have never encountered this bug myself, and I don't think it's very common.
What results do you get with the following test program? The times should be mostly increasing in value, but you are liable to get one or two out of order just because their threads get rescheduled just after they've read a value and before they add it to the queue.
namespace Demo
{
class Program
{
Stopwatch sw = Stopwatch.StartNew();
object locker = new object();
ConcurrentQueue<long> queue = new ConcurrentQueue<long>();
Barrier barrier = new Barrier(9);
void run()
{
Console.WriteLine("Starting");
for (int i = 0; i < 8; ++i)
Task.Run(()=>test());
barrier.SignalAndWait(); // Make sure all threads start "simultaneously"
Thread.Sleep(2000); // Plenty of time for all the threads to finish.
Console.WriteLine("Stopped");
foreach (var elapsed in queue)
Console.WriteLine(elapsed);
Console.ReadLine();
}
void test()
{
barrier.SignalAndWait(); // Make sure all threads start "simultaneously".
for (int i = 0; i < 10; ++i)
queue.Enqueue(elapsed());
}
long elapsed()
{
lock (locker)
{
return sw.ElapsedTicks;
}
}
static void Main()
{
new Program().run();
}
}
}
Having said all that, the most obvious answer is that in fact you aren't sharing a single Stopwatch between the threads, but instead you have accidentally started a new one for each thread...

pausing program without interrupting timers c#

I am writing a program that has several "Worker" objects going off and doing tasks that take as set amount of time. I have created a worker class with an internal timer that is working fine. However, when doing the "work" i will at times need to wait several seconds for a screen refresh (each worker is scraping data from a remote screen and doing some automation).
For those pauses, i don't want to sleep the thread, because as i understand it that will also
pause the timers on the other worker objects (my application is a single thread because, frankly, I'm brand new to C# and i didn't want to overreach). Is there another waiting function that i can use that doesn't actually hang the whole thread?
Some additional info:
Right now this is a console app, but i will eventually be building a UI form to provide feedback to the user on how the workers are doing
My timers are implemented using System.Timers and are working quite nicely
I am brand new to C# programming, this is my first project, so please use small words ;)
Using MS VS Express 2012 for Desktop (so whatever version of C# / .NET that is!)
Code below (the actual work will be done using the "startWorking" method, but nothing is implemented - this is just my sold build with timers working. Also, the main is just being used for testing multiple timers right now)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace Multi_Timers
{
//worker class that includes a timer
public class Worker
{
private Timer taskTimer;
private bool available = true;
private string workerName;
private string startWork;
private int workTime;
// properties
public bool isAvailable { get { return this.available; } }
public string name { get { return this.workerName; } }
// constructor
public Worker(string name)
{
this.workerName = name;
Console.WriteLine("{0} is initialized", name);
}
// start work timer
public void startWorking(int duration) {
if (this.available == true)
{
this.available = false;
this.taskTimer = new Timer();
this.taskTimer.Interval = duration;
this.taskTimer.Elapsed += new ElapsedEventHandler(doneWorking);
this.taskTimer.Enabled = true;
this.startWork = DateTime.Now.ToString();
this.workTime = duration / 1000;
}
else Console.WriteLine("Sorry, {0} was not available to work", this.workerName);
}
// Handler for timer
public void doneWorking(object sender, ElapsedEventArgs e)
{
Console.WriteLine("{0}: {1} / {2} min / {3}", this.workerName, this.startWork, this.workTime/60, e.SignalTime.ToLocalTime());
this.taskTimer.Enabled = false;
this.available = true;
}
}
//main program
class Program
{
static void Main(string[] args)
{
Random r = new Random();
// initialize worker(s)
Worker bob = new Worker("Bob");
Worker bill = new Worker("Bill");
Worker jim = new Worker("Jim");
// q to exit
while (true)
{
if (bob.isAvailable) {
bob.startWorking(r.Next(1 * 60, 150 * 60) * 1000);
}
if (bill.isAvailable)
{
bill.startWorking(r.Next(1 * 60, 150 * 60) * 1000);
}
if (jim.isAvailable)
{
jim.startWorking(r.Next(1 * 60, 150 * 60) * 1000);
}
}
}
}
}
Thank you for any help in advance! Reading examples from this community was definitely key in teaching myself a little bit of C# to get started with!
i don't want to sleep the thread, because as i understand it that will also pause the timers on the other worker objects
That is incorrect; it will not stop the timers.
my application is a single thread
No, actually, it's not. The timers will be creating and using other threads to implement their behavior. The Elapsed event handlers will be fired from a thread pool thread.
One major issue with your code is that your main method is doing a "busywait" on the three objects, constantly polling them asking if they're done. This is...expensive. It's basically like you're kids asking, "Are we there yet." a few hundred times a second. Wouldn't it be so much nicer if they just sat their waiting until you told them you were done! (That's quite possible, and a good possible option.)
One of the simpler solutions in this case would be to do the loop in the worker, not Main. Have the implementation of startWorking wrapped in a while loop, and have main just do a wait forever (i.e. Thread.Sleep(Timeout.Infinite);). More complex options would be having the workers provide a Task, event, or blocking wait (also called a "Join") method to indicate when they are finished.
The option you're considering, that of adding a Thread.Sleep of a little while in Main will help, but it's only telling your kids to ask you when you're there less often, rather than having them wait for you to tell them when you're there.
If you ever find yourself wanting to delay execution again in a different context you could consider an implementation like this:
private static void DelayExecution(Action action, TimeSpan delay)
{
TimeSpan start = DateTime.Now.TimeOfDay;
Thread t = new Thread(() =>
{
while (DateTime.Now.TimeOfDay < start.Add(delay))
{
//Block
}
action.Invoke();
});
t.Start();
}
private static void Main(string[] args)
{
DelayExecution(() => Console.WriteLine("Delayed Execution"), TimeSpan.FromSeconds(1));
Console.ReadLine();
}

Categories