Запустить другой код, пока таймер работает в c# - PullRequest
1 голос
/ 06 мая 2020

Я делаю C# консольный математический тест, в котором пользователь отвечает на математические вопросы

Я пытаюсь добавить таймер в тест, но я не могу запустить свой таймер одновременно с мой другой код

Вот пример моего кода:

class Program
{
    public static OtherCode()
    {
        \\*other code for test
    }
    public class Timer
    {
        public static int Timers(int timeLeft)
        {
            do
            {
                Console.Write("\rtimeLeft: {0} ", timeLeft);
                timeLeft--;
                Thread.Sleep(1000);
            } while (timeLeft > 0);
            Console.Write(Environment.NewLine);
            return timeLeft;
        }
    }

    public static void Main(string[] args)
    {
        int numberOfSeconds = 30;
        Timer.Timers(numberOfSeconds);

        \\other code
        OtherCode();
    }
}

Вот мой полный код: https://github.com/CrazyDanyal1414/mathstester

Я бы хотел мой таймер должен работать в верхней части консоли, а математические вопросы должны быть заданы ниже, как это, за исключением того, что вопрос должен быть в новой строке: enter image description here

Любая помощь приветствуется!

ОБНОВЛЕНИЕ

Когда я добавляю Console.SetCursorPosition () в свой код следующим образом:

do
    {
        Console.SetCursorPosition(0, 9);        
        Console.Write("\rtimeLeft: {0} ", timeLeft);
        timeLeft--;
        Thread.Sleep(1000);
    } while (timeLeft > 0);

Мой код не перемещает таймер, но когда я набираю ответ на один из своих математических вопросов, он заставляет меня вводить его в той же строке, что и таймер, например: enter image description here

Ответы [ 3 ]

1 голос
/ 06 мая 2020

Чтобы сообщение о состоянии оставалось в нижней части консоли, вам нужен способ манипулировать экранным буфером, чтобы вы постоянно перезаписывали свое сообщение о состоянии.

Для этого можно использовать Console.SetCursorPos и полезен в более продвинутом сценарии ios, но я думаю, что вы можете обойтись простым использованием \ r для сброса курсора в начало строки.

Доказательство концепции:

using System;

namespace consoletimer
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            int numberOfSeconds = 300;
            var thread = new System.Threading.Thread(()=> PrintStatusMessage(numberOfSeconds));
            thread.Start();
            int n = 5;
            while(n-- > 0){
                WriteToScreen("Example text", false);
                ReadInput();
                System.Threading.Thread.Sleep(2000);
            }
        }

        static void PrintStatusMessage(int numberOfSeconds){
            var whenToStop = DateTime.Now.AddSeconds(numberOfSeconds);
            while(DateTime.Now < whenToStop){
                var timeLeft = (whenToStop-DateTime.Now).ToString(@"hh\:mm\:ss");
                WriteToScreen($"Time Remaining: {timeLeft}", true);
                System.Threading.Thread.Sleep(500);
            }
        }

        static string ReadInput(){
            string input = Console.ReadLine();
            Console.Write(new string(' ',100));
            Console.CursorLeft = 0;
            return input;
        }

        static object lockObject = new object();

        static void WriteToScreen(string message, bool resetCursor){
            lock(lockObject){
                if(resetCursor){
                    int leftPos = Console.CursorLeft;
                    Console.WriteLine();
                    Console.Write(message.PadRight( 50, ' '));
                    Console.CursorTop--;
                    Console.CursorLeft = leftPos;
                }
                else{
                    Console.WriteLine(message);
                    Console.Write(new string(' ',100));
                    Console.CursorLeft = 0;
                }   
            }
        }
    }    
}

Изменить

Нам нужно очищать следующую строку всякий раз, когда мы пишем в консоль, чтобы мы удалили сообщение о статусе, которое было там ранее.

1 голос
/ 06 мая 2020

Вы можете запустить метод Timers во втором потоке.

Для этого вам нужно использовать System.Threading Namespace. Взгляните на: Start Parameterized Thread

0 голосов
/ 06 мая 2020

, вы можете просто использовать потоки таким образом

using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        public static void OtherCode()
        {
            Console.ReadKey();
            //other code for test
        }

        public static void Main(string[] args)
        {

            Thread thread = new Thread(new ThreadStart(Job));
            thread.Start();

            //other code
            OtherCode();
        }

        public static void Job()
        {
            int numberOfSeconds = 30;
            Timer.Timers(numberOfSeconds);
        }
    }

    class Timer
    {
        public static int Timers(int timeLeft)
        {
            do
            {
                Console.Write("\rtimeLeft: {0} ", timeLeft);
                timeLeft--;
                Thread.Sleep(1000);
            } while (timeLeft > 0);
            Console.Write(Environment.NewLine);
            return timeLeft;
        }
    }
}

или

    public static void Main(string[] args)
    {

        Thread thread = new Thread(new ThreadStart(() => {
            int numberOfSeconds = 30;
            Timer.Timers(numberOfSeconds);
        }));
        thread.Start();

        //other code
        OtherCode();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...