-1

I'm currently working on a hobby project involving a console application. In my program, I fetch data, transform it and eventually it gets parsed to json. The rough structure looks like this:

static void Main(string[] args)
{
    var sw = new Stopwatch();
    var worker = new Worker();
    var start = DateTime.Now;
    var workSpeed = 0.0;
    Console.WriteLine($"Initialisation started at {start}");
    sw.Start();
    var materials = worker.GatherMaterials();
    var workStart = DateTime.Now;
    Console.WriteLine($"Work started at {workStart}.");
    var products = new List<Product>();
    foreach (var material in materials)
    {
        try
        {
            var product = worker.Process(material);
            products.Add(product);
            sw.Stop();
            workSpeed = (double)products.Count / sw.Elapsed.TotalSeconds;
            sw.Start();   
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            break;
        }
    }
    sw.Stop();
    Console.WriteLine();
    var finish = DateTime.Now;
    Console.WriteLine($"Work finished at {finish}");
    Console.WriteLine($"Ran from {start} to {finish} for approximately {sw.Elapsed} ms.");
    Console.WriteLine($"Processed {products.Count} products for an average processing speed of {workSpeed} products/s.");
    var jsonOptions = new JsonSerializerOptions()
    {
        Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
        WriteIndented = true
    };
    var json = JsonSerializer.Serialize(products, jsonOptions);
    File.WriteAllText("products.json", json, Encoding.UTF8);
    Console.WriteLine("Saved all products to products.json");
}

There's a bit of code inside the try block where I temporarily stop the stopwatch to update the processing speed. I did this so that I could put a break point there to check the processing speed. However, I don't want to always run this application in debug mode. Ideally, I'd like to get rid of the part where I stop and resume the stopwatch and instead to have a way to interact with the variables directly through the console.

For example, would it be possible to have a persistent question in the terminal that says something like Press S to get the current processing speed, so that the value of the workSpeed variable shows up whenever I press S?

JansthcirlU
  • 688
  • 5
  • 21
  • You can create another thread that waits for S to be pressed and using Console.ReadKey the writes the value of workSpeed. – Sherif Elmetainy May 25 '21 at 19:51
  • Not sure who closed this question, but with two people mentioning working with different threads, I'm curious to see if anyone can provide an answer that would illustrate that approach. – JansthcirlU May 25 '21 at 20:06
  • In the first duplicate link it provides an example of using a separate thread – Rufus L May 25 '21 at 20:23
  • 1
    when I posted my comment yesterday, I didn't have time to post answer with code. Since the question is closed now, here is a [git gist](https://gist.github.com/sherif-elmetainy/96716c0b28f2ef1eab8a3c10f39c3dab) with code on how to do it with a thread. – Sherif Elmetainy May 26 '21 at 03:58
  • Thanks @SherifElmetainy, I'll have a look! – JansthcirlU May 26 '21 at 07:37

2 Answers2

0

You can check the value of Console.KeyAvailable to see if the user pressed a key (it will be true if they did), and then use Console.ReadKey(true) to capture the key that they pressed (true means it won't be displayed).

For example:

var sw = new Stopwatch();

Console.WriteLine("Press 'S' to display the elapsed time, 'Q' to quit...");

sw.Start();

while (true)
{
    if (Console.KeyAvailable)
    {
        var input = Console.ReadKey(true).Key;

        if (input == ConsoleKey.S)
        {
            Console.WriteLine($"Elapsed time: {sw.Elapsed.ToString("c")}");
        }
        else if (input == ConsoleKey.Q)
        {
            break;
        }
    }
}

sw.Stop();

Console.WriteLine($"All done. Total elapsed time: {sw.Elapsed.ToString("c")}");
Console.Write("Press any key to exit...");
Console.ReadKey(true);
Rufus L
  • 36,127
  • 5
  • 30
  • 43
  • So for my code, I would put the `KeyAvailable` logic inside my `foreach` loop, right? – JansthcirlU May 25 '21 at 19:56
  • @JansthcirlU Correct, along with the other code in your loop. This is just a few lines that check for user input, and if it's a value we care about, displays something to the console and then keep on loopin' – Rufus L May 25 '21 at 19:58
  • Thanks for the help, I'll give that a shot if I have the chance. It could be a while before I can report on the results, just a heads up. – JansthcirlU May 25 '21 at 20:01
  • No hurry. Better to wait a while in case a better answer comes in anyway. :) – Rufus L May 25 '21 at 20:02
-1

I think the best alternative is to go for a multithreaded approach: keep your actual logic in a separate thread, and have the main thread handle the queries you're interested in. Note that with a multithreaded approach you will need to have shared resources between the 2 threads (and eventually do some synchronization), in order to get the rate you're interested in.