콘솔 애플리케이션 진행률 표시줄

13132 단어 dotnet
누구나 한 번쯤은 콘솔 애플리케이션에서 진행률 표시줄을 본 적이 있을 것입니다. 이번 주에 저는 저만의 진행률 표시줄 시스템을 구축해 보기로 했습니다.

다음은 내가 생각해낸 진행률 표시줄 클래스를 살펴보겠습니다. 디자인은 매우 간단합니다.

class ProgressBar
{
    private readonly int length;

    public ProgressBar(int length)
    {
        this.length = length;
    }

    public string GetUpdate(int progress)
    {
        progress /= 100 / this.length;

        string progressString = string.Empty;
        for (int i = 0; i < progress; i++)
        {
            progressString = $"{progressString}-";
        }

        string remainderString = string.Empty;
        for (int i = 0; i < this.length - progress; i++)
        {
            remainderString = $"{remainderString} ";
        }

        return $"{progressString}{remainderString}";
    }
}

진행률 표시줄의 길이(문자)를 제어하는 ​​길이 필드가 있습니다. GetUpdate 메서드에서 상대 진행률(백분율) 길이를 얻기 위해 간단한 수학을 하고 있습니다. 그런 다음 진행 길이를 반복하고 진행 문자열에 대시를 추가합니다. 마지막으로 진행률 표시줄에서 진행률 길이를 뺀 길이를 반복하고 나머지 문자열에 공백 문자를 추가한 다음 두 값의 보간을 반환합니다.

이 클래스는 우리가 선택한 모든 것의 진행 상황을 나타내는 데 사용할 수 있지만, 저는 시스템의 프로세서 시간을 추적하는 응용 프로그램을 만들고 싶었습니다. 다음은 내 구현입니다.

class Program
{
    static List<int> percentages;

    static ProgressBar processorTimeBar;

    static System.Diagnostics.PerformanceCounter processorCounter;

    static System.Timers.Timer timer;
    static System.Timers.Timer processorTimer;

    static void Main(string[] args)
    {
        Console.CursorVisible = false;

        processorCounter = new System.Diagnostics.PerformanceCounter("Processor", "% Processor Time", "_Total");

        processorTimeBar = new ProgressBar(50);

        percentages = new List<int>();

        timer = new System.Timers.Timer();
        timer.Interval = 200;

        processorTimer = new System.Timers.Timer();
        processorTimer.Interval = 50;

        timer.Elapsed += Update;
        timer.Enabled = true;

        processorTimer.Elapsed += UpdatePercentages;
        processorTimer.Enabled = true;

        Console.ReadLine();
    }

    static void Update(object sender, System.Timers.ElapsedEventArgs e)
    {
        Console.Write("Processor Time: [");
        Console.ForegroundColor = ConsoleColor.Green;
        Console.Write(processorTimeBar.GetUpdate((int)percentages.Average()));
        Console.ResetColor();
        Console.Write(']');
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine($" {(int)percentages.Average():000}%");
        Console.ResetColor();
        Console.WriteLine("Press any key to exit . . . ");
        Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop - 2);
        percentages = new List<int>();
    }

    static void UpdatePercentages(object sender, System.Timers.ElapsedEventArgs e)
    {
        percentages.Add((int)processorCounter.NextValue());
    }
}

(솔직히) 진행률 표시줄 클래스의 자식이나 진행률 표시줄 클래스 자체에서 추상화되어야 하는 몇 가지 주목할 만한 코드 줄이 있습니다.

먼저 Console.CursorVisible = false; 행을 볼 수 있습니다. 이것은 당연할 수 있지만 이 줄은 커서가 응용 프로그램에서 렌더링되는 것을 방지합니다. 프로그래밍 방식으로 커서의 위치를 ​​빠르게 변경하므로 뇌졸중이 발생하지 않습니다. 그러나 터미널의 아무 곳이나 클릭하면 빠른 편집 모드가 활성화되어 커서 가시성과 위치가 레일에서 벗어납니다. 이 문제에 대한 솔루션을 구현하려는 경우 응용 프로그램 실행 중 빠른 편집 기능을 비활성화하는 this 접근 방식을 살펴볼 수 있습니다.

다음으로 두 타이머의 경과 이벤트를 각각 구독하는 두 함수를 볼 수 있습니다. 이것은 꼭 필요한 것은 아니지만 업데이트 함수가 호출될 때 즉각적인 표현보다는 프로세서 시간의 평균을 원했습니다. 목록을 사용하여 50밀리초마다 프로세서 시간을 저장하고 초당 5번 호출되는 업데이트 함수 내에서 목록을 재설정합니다.

마지막으로 업데이트 메서드 내에서 Console.SetCursorPosition를 호출하여 이전 줄을 덮어쓸 수 있습니다. 이것은 고정 진행률 표시줄의 환상을 만듭니다.

쓰기 전에 줄을 지우지 않으면 덮어쓰지 않은 문자가 계속 표시된다는 점에 유의하는 것이 중요합니다. 이 동작을 방지하기 위한 나의 간단한 전략은 이 문제를 해결할 수 있는 끝없는 방법이 있지만 백분율 출력 형식을 세 개의 공백으로 지정하는 것입니다.

이 작업을 하는 것은 매우 재미있었고 원래 생각했던 것보다 놀라울 정도로 훨씬 간단했습니다. 이것이 전통적으로 그러한 기능을 구현하는 방법에 가까운지 확신할 수 없지만 앞으로는 다른 전략을 찾는 것이 즐거울 것입니다.

좋은 웹페이지 즐겨찾기