Làm cách nào để cập nhật dòng hiện tại trong Ứng dụng Bảng điều khiển Windows C #?


507

Khi xây dựng Ứng dụng Windows Console trong C #, có thể ghi vào bảng điều khiển mà không phải mở rộng dòng hiện tại hoặc chuyển sang dòng mới không? Ví dụ: nếu tôi muốn hiển thị tỷ lệ phần trăm biểu thị mức độ hoàn thành của một quá trình, tôi chỉ muốn cập nhật giá trị trên cùng một dòng với con trỏ và không phải đặt từng phần trăm trên một dòng mới.

Điều này có thể được thực hiện với ứng dụng bảng điều khiển C # "tiêu chuẩn" không?


Nếu bạn thực sự quan tâm đến các giao diện dòng lệnh thú vị, bạn nên kiểm tra các lời nguyền / lời nguyền.
Charles Addis

@CharlesAddis nhưng không chửi / ncurses chỉ hoạt động trong C ++?
Xam

Câu trả lời:


783

Nếu bạn chỉ in "\r"lên bàn điều khiển, con trỏ sẽ quay trở lại đầu dòng hiện tại và sau đó bạn có thể viết lại. Cái này cần phải dùng mẹo:

for(int i = 0; i < 100; ++i)
{
    Console.Write("\r{0}%   ", i);
}

Lưu ý một vài khoảng trắng sau số để đảm bảo rằng mọi thứ đã có trước đó đều bị xóa.
Cũng lưu ý việc sử dụng Write()thay vì WriteLine()vì bạn không muốn thêm "\ n" ở cuối dòng.


7
for (int i = 0; i <= 100; ++ i) sẽ đạt 100%
Nicolas Tyler

13
Làm thế nào để bạn xử lý khi viết trước đó dài hơn viết mới? Có một số cách để có được chiều rộng của giao diện điều khiển và đệm dòng với không gian, có thể?
vẽ Chapin

6
@druciferre Ra khỏi đỉnh đầu tôi có thể nghĩ ra hai câu trả lời cho câu hỏi của bạn. Cả hai đều liên quan đến việc lưu đầu ra hiện tại dưới dạng một chuỗi trước tiên và đệm nó với một số lượng ký tự như thế này: Console.Write ("\ r {0}", strOutput.PadRight (nPaddingCount, '')); "NPaddingCount" có thể là một số mà bạn tự đặt hoặc bạn có thể theo dõi đầu ra trước đó và đặt nPaddingCount là chênh lệch độ dài giữa đầu ra hiện tại và đầu ra hiện tại cộng với độ dài đầu ra hiện tại. Nếu nPaddingCount âm tính thì bạn sẽ không phải sử dụng PadRight trừ khi bạn thực hiện abs (trước.len - current.len).
John Odom

1
@machem Mã tổ chức tốt. Nếu bất kỳ chủ đề nào trong số hàng chục chủ đề có thể ghi vào bảng điều khiển bất cứ lúc nào nó muốn, điều đó sẽ mang đến cho bạn những rắc rối bất kể bạn có viết những dòng mới hay không.
Đánh dấu

2
@JohnOdom bạn chỉ cần giữ độ dài đầu ra (không được đệm) trước đó, sau đó cung cấp đó làm đối số đầu tiên cho PadRight(tất nhiên là lưu chuỗi không đệm, hoặc chiều dài, trước tiên).
Jesper Matthiesen

254

Bạn có thể sử dụng Console.SetCursorPositionđể đặt vị trí của con trỏ và sau đó viết tại vị trí hiện tại.

Dưới đây là một ví dụ cho thấy một "spinner" đơn giản:

static void Main(string[] args)
{
    var spin = new ConsoleSpinner();
    Console.Write("Working....");
    while (true) 
    {
        spin.Turn();
    }
}

public class ConsoleSpinner
{
    int counter;

    public void Turn()
    {
        counter++;        
        switch (counter % 4)
        {
            case 0: Console.Write("/"); counter = 0; break;
            case 1: Console.Write("-"); break;
            case 2: Console.Write("\\"); break;
            case 3: Console.Write("|"); break;
        }
        Thread.Sleep(100);
        Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
    }
}

Lưu ý rằng bạn sẽ phải đảm bảo ghi đè bất kỳ đầu ra hiện có với đầu ra mới hoặc khoảng trống.

Cập nhật: Vì đã bị chỉ trích rằng ví dụ này chỉ di chuyển con trỏ trở lại bởi một ký tự, tôi sẽ thêm phần này để làm rõ: Sử dụng SetCursorPositionbạn có thể đặt con trỏ đến bất kỳ vị trí nào trong cửa sổ giao diện điều khiển.

Console.SetCursorPosition(0, Console.CursorTop);

sẽ đặt con trỏ về đầu dòng hiện tại (hoặc bạn có thể sử dụng Console.CursorLeft = 0trực tiếp).


8
Vấn đề có thể được giải quyết bằng cách sử dụng \ r, nhưng sử dụng SetCursorPosition(hoặc CursorLeft) cho phép linh hoạt hơn, ví dụ như không viết ở đầu dòng, di chuyển lên trong cửa sổ, v.v ... vì vậy đây là cách tiếp cận tổng quát hơn có thể được sử dụng để đầu ra thanh tiến trình tùy chỉnh hoặc đồ họa ASCII.
Dirk Vollmar

14
+1 vì dài dòng và vượt lên trên và vượt ra ngoài nhiệm vụ. Tốt thứ cảm ơn.
Copas

1
+1 để hiển thị một cách làm khác. Mọi người khác đã hiển thị và nếu OP chỉ cập nhật phần trăm, với điều này, anh ta chỉ có thể cập nhật giá trị mà không phải viết lại toàn bộ dòng. OP thực sự chưa bao giờ nói rằng anh ấy muốn chuyển đến đầu dòng, chỉ là anh ấy muốn cập nhật một cái gì đó trên cùng một dòng với con trỏ.
Andy

1
Tính linh hoạt được thêm vào của SetC bổngPocation có giá của một chút tốc độ và một con trỏ nhấp nháy đáng chú ý nếu vòng lặp đủ dài để người dùng chú ý. Xem bình luận thử nghiệm của tôi dưới đây.
Kevin

5
Đồng thời xác nhận rằng độ dài dòng không làm cho bàn điều khiển bao bọc sang dòng tiếp theo hoặc bạn có thể gặp sự cố với nội dung chạy xuống cửa sổ giao diện điều khiển.
Mandrake

84

Cho đến nay chúng ta có ba lựa chọn thay thế cạnh tranh để làm điều này:

Console.Write("\r{0}   ", value);                      // Option 1: carriage return
Console.Write("\b\b\b\b\b{0}", value);                 // Option 2: backspace
{                                                      // Option 3 in two parts:
    Console.SetCursorPosition(0, Console.CursorTop);   // - Move cursor
    Console.Write(value);                              // - Rewrite
}

Tôi đã luôn sử dụng Console.CursorLeft = 0, một biến thể của tùy chọn thứ ba, vì vậy tôi quyết định thực hiện một số thử nghiệm. Đây là mã tôi đã sử dụng:

public static void CursorTest()
{
    int testsize = 1000000;

    Console.WriteLine("Testing cursor position");
    Stopwatch sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < testsize; i++)
    {
        Console.Write("\rCounting: {0}     ", i);
    }
    sw.Stop();
    Console.WriteLine("\nTime using \\r: {0}", sw.ElapsedMilliseconds);

    sw.Reset();
    sw.Start();
    int top = Console.CursorTop;
    for (int i = 0; i < testsize; i++)
    {
        Console.SetCursorPosition(0, top);        
        Console.Write("Counting: {0}     ", i);
    }
    sw.Stop();
    Console.WriteLine("\nTime using CursorLeft: {0}", sw.ElapsedMilliseconds);

    sw.Reset();
    sw.Start();
    Console.Write("Counting:          ");
    for (int i = 0; i < testsize; i++)
    {        
        Console.Write("\b\b\b\b\b\b\b\b{0,8}", i);
    }

    sw.Stop();
    Console.WriteLine("\nTime using \\b: {0}", sw.ElapsedMilliseconds);
}

Trên máy của tôi, tôi nhận được các kết quả sau:

  • Không gian sau: 25,0 giây
  • Vận chuyển trở lại: 28,7 giây
  • SetCthonP vị trí: 49,7 giây

Ngoài ra, SetCursorPositiongây ra nhấp nháy đáng chú ý mà tôi đã không quan sát với một trong những lựa chọn thay thế. Vì vậy, đạo đức là sử dụng các khoảng trống hoặc trả lại xe khi có thể , và cảm ơn vì đã dạy tôi một cách nhanh hơn để làm điều này, SO!


Cập nhật : Trong các bình luận, Joel gợi ý rằng SetCthonPocation không đổi đối với khoảng cách di chuyển trong khi các phương thức khác là tuyến tính. Thử nghiệm thêm xác nhận rằng đây là trường hợp, tuy nhiên thời gian liên tục và chậm vẫn chậm. Trong các thử nghiệm của tôi, việc viết một chuỗi dài các khoảng trống vào bảng điều khiển nhanh hơn SetC bổngPocation cho đến khoảng 60 ký tự. Vì vậy, backspace nhanh hơn để thay thế các phần của dòng ngắn hơn 60 ký tự (hoặc hơn) nó không nhấp nháy, vì vậy tôi sẽ đứng trước sự chứng thực ban đầu của tôi về \ b trên \ r và SetCursorPosition.


4
Hiệu quả của hoạt động trong câu hỏi thực sự không nên quan trọng. Tất cả sẽ xảy ra quá nhanh để người dùng chú ý. Vi mô không cần thiết là xấu.
Malfist

@Malfist: Tùy thuộc vào độ dài của vòng lặp, người dùng có thể hoặc không thể nhận thấy. Như tôi đã thêm trong phần chỉnh sửa ở trên (trước khi tôi thấy bình luận của bạn), SetC bổngPocation đã giới thiệu nhấp nháy và mất gần gấp đôi so với các tùy chọn khác.
Kevin

1
Tôi đồng ý rằng đó là một tối ưu hóa vi mô (chạy nó một triệu lần và mất 50 giây vẫn là một khoảng thời gian rất nhỏ), +1 cho kết quả và chắc chắn có thể rất hữu ích khi biết.
Andy

6
Các tiêu chuẩn về cơ bản là thiếu sót. Có thể thời gian SetCthonP vị trí () là như nhau cho dù con trỏ di chuyển bao xa, trong khi các tùy chọn khác thay đổi theo số lượng ký tự mà bàn điều khiển phải xử lý.
Joel Coehoorn

1
Đây là một tổng hợp rất tốt đẹp của các tùy chọn khác nhau có sẵn. Tuy nhiên, tôi cũng thấy nhấp nháy khi sử dụng \ r. Với \ b rõ ràng là không nhấp nháy vì văn bản sửa lỗi ("Đếm:") không được viết lại. Bạn cũng sẽ bị nhấp nháy nếu bạn thêm \ b và viết lại văn bản sửa lỗi như đang xảy ra với \ b và SetCthonPocation. Liên quan đến nhận xét của Joel: Joel về cơ bản là đúng, tuy nhiên \ r vẫn sẽ vượt trội hơn SetC bổngPocation trên các dòng rất dài, nhưng sự khác biệt sẽ ít hơn.
Dirk Vollmar

27

Bạn có thể sử dụng \ b chuỗi thoát (backspace) để sao lưu một số ký tự cụ thể trên dòng hiện tại. Điều này chỉ di chuyển vị trí hiện tại, nó không loại bỏ các ký tự.

Ví dụ:

string line="";

for(int i=0; i<100; i++)
{
    string backup=new string('\b',line.Length);
    Console.Write(backup);
    line=string.Format("{0}%",i);
    Console.Write(line);
}

Ở đây, dòngdòng phần trăm để ghi vào bàn điều khiển. Mẹo nhỏ là tạo đúng số ký tự \ b cho đầu ra trước đó.

Ưu điểm của phương pháp này so với phương pháp \ r là nếu hoạt động ngay cả khi phần trăm đầu ra của bạn không ở đầu dòng.


1
+1, đây hóa ra là phương pháp nhanh nhất được trình bày (xem nhận xét thử nghiệm của tôi bên dưới)
Kevin

19

\rđược sử dụng cho các kịch bản này.
\r đại diện cho lợi nhuận vận chuyển có nghĩa là con trỏ trở về đầu dòng.
Đó là lý do tại sao Windows sử dụng \n\rlàm điểm đánh dấu dòng mới.
\ndi chuyển bạn xuống một dòng và đưa \rbạn trở lại đầu dòng.


22
Ngoại trừ nó thực sự \ r \ n.
Joel Mueller

14

Tôi chỉ phải chơi với ConsoleSpinnerlớp của divo . Của tôi không ở đâu gần như súc tích, nhưng điều đó không phù hợp với tôi rằng người dùng của lớp đó phải viết while(true)vòng lặp của riêng họ . Tôi đang chụp cho một trải nghiệm như thế này:

static void Main(string[] args)
{
    Console.Write("Working....");
    ConsoleSpinner spin = new ConsoleSpinner();
    spin.Start();

    // Do some work...

    spin.Stop(); 
}

Và tôi nhận ra nó với mã dưới đây. Vì tôi không muốn Start()phương thức của mình bị chặn, tôi không muốn người dùng phải lo lắng về việc viếtwhile(spinFlag) vòng lặp giống như tôi và tôi muốn cho phép nhiều spinners cùng một lúc tôi phải tạo ra một luồng riêng biệt để xử lý quay. Và điều đó có nghĩa là mã phải phức tạp hơn rất nhiều.

Ngoài ra, tôi đã không thực hiện nhiều luồng đa năng đến mức có thể (thậm chí có thể) rằng tôi đã để lại một lỗi tinh vi hoặc ba trong đó. Nhưng nó dường như hoạt động khá tốt cho đến nay:

public class ConsoleSpinner : IDisposable
{       
    public ConsoleSpinner()
    {
        CursorLeft = Console.CursorLeft;
        CursorTop = Console.CursorTop;  
    }

    public ConsoleSpinner(bool start)
        : this()
    {
        if (start) Start();
    }

    public void Start()
    {
        // prevent two conflicting Start() calls ot the same instance
        lock (instanceLocker) 
        {
            if (!running )
            {
                running = true;
                turner = new Thread(Turn);
                turner.Start();
            }
        }
    }

    public void StartHere()
    {
        SetPosition();
        Start();
    }

    public void Stop()
    {
        lock (instanceLocker)
        {
            if (!running) return;

            running = false;
            if (! turner.Join(250))
                turner.Abort();
        }
    }

    public void SetPosition()
    {
        SetPosition(Console.CursorLeft, Console.CursorTop);
    }

    public void SetPosition(int left, int top)
    {
        bool wasRunning;
        //prevent other start/stops during move
        lock (instanceLocker)
        {
            wasRunning = running;
            Stop();

            CursorLeft = left;
            CursorTop = top;

            if (wasRunning) Start();
        } 
    }

    public bool IsSpinning { get { return running;} }

    /* ---  PRIVATE --- */

    private int counter=-1;
    private Thread turner; 
    private bool running = false;
    private int rate = 100;
    private int CursorLeft;
    private int CursorTop;
    private Object instanceLocker = new Object();
    private static Object console = new Object();

    private void Turn()
    {
        while (running)
        {
            counter++;

            // prevent two instances from overlapping cursor position updates
            // weird things can still happen if the main ui thread moves the cursor during an update and context switch
            lock (console)
            {                  
                int OldLeft = Console.CursorLeft;
                int OldTop = Console.CursorTop;
                Console.SetCursorPosition(CursorLeft, CursorTop);

                switch (counter)
                {
                    case 0: Console.Write("/"); break;
                    case 1: Console.Write("-"); break;
                    case 2: Console.Write("\\"); break;
                    case 3: Console.Write("|"); counter = -1; break;
                }
                Console.SetCursorPosition(OldLeft, OldTop);
            }

            Thread.Sleep(rate);
        }
        lock (console)
        {   // clean up
            int OldLeft = Console.CursorLeft;
            int OldTop = Console.CursorTop;
            Console.SetCursorPosition(CursorLeft, CursorTop);
            Console.Write(' ');
            Console.SetCursorPosition(OldLeft, OldTop);
        }
    }

    public void Dispose()
    {
        Stop();
    }
}

Sửa đổi tốt đẹp, mặc dù mã mẫu không phải là của tôi. Nó được lấy từ blog của Brad Abrams (xem liên kết trong câu trả lời của tôi). Tôi nghĩ rằng nó chỉ được viết dưới dạng một mẫu đơn giản thể hiện SetC bổngPocation. Btw, tôi chắc chắn ngạc nhiên (theo cách tích cực) về cuộc thảo luận bắt đầu về những gì tôi nghĩ chỉ là một mẫu đơn giản. Đó là lý do tại sao tôi thích trang web này :-)
Dirk Vollmar

4

Hoàn toàn sử dụng Trả về Carrage (\ r) ở đầu dòng thay vì (ngầm hoặc rõ ràng) sử dụng Dòng mới (\ n) ở cuối sẽ nhận được những gì bạn muốn. Ví dụ:

void demoPercentDone() {
    for(int i = 0; i < 100; i++) {
        System.Console.Write( "\rProcessing {0}%...", i );
        System.Threading.Thread.Sleep( 1000 );
    }
    System.Console.WriteLine();    
}

-1, Câu hỏi yêu cầu C #, tôi viết lại bằng C # và bạn đổi lại thành F #
Malfist

Có vẻ như một cuộc xung đột chỉnh sửa thay vì anh ta thay đổi C # của bạn thành F #. Thay đổi của anh ấy là một phút sau của bạn, và tập trung vào chạy nước rút.
Andy

Cảm ơn đã chỉnh sửa. Tôi có xu hướng sử dụng chế độ tương tác F # để kiểm tra mọi thứ và tìm ra các phần quan trọng là các cuộc gọi BCL, giống như trong C #.
James Hugard

3
    public void Update(string data)
    {
        Console.Write(string.Format("\r{0}", "".PadLeft(Console.CursorLeft, ' ')));
        Console.Write(string.Format("\r{0}", data));
    }

1

Từ tài liệu Console trong MSDN:

Bạn có thể giải quyết vấn đề này bằng cách đặt thuộc tính TextWriter.NewLine của thuộc tính Out hoặc Error thành chuỗi kết thúc dòng khác. Ví dụ: câu lệnh C #, Console.Error.NewLine = "\ r \ n \ r \ n";, đặt chuỗi kết thúc dòng cho luồng đầu ra lỗi tiêu chuẩn thành hai chuỗi trả về dòng và dòng cấp dữ liệu. Sau đó, bạn có thể gọi một cách rõ ràng phương thức WriteLine của đối tượng luồng đầu ra lỗi, như trong câu lệnh C #, Console.Error.WriteLine ();

Vì vậy - tôi đã làm điều này:

Console.Out.Newline = String.Empty;

Sau đó, tôi có thể tự kiểm soát đầu ra;

Console.WriteLine("Starting item 1:");
    Item1();
Console.WriteLine("OK.\nStarting Item2:");

Một cách khác để đạt được điều đó.


Bạn chỉ có thể sử dụng Console.Write () cho cùng một mục đích mà không cần xác định lại thuộc tính NewLine ...
Radosław Gers

1

Điều này hoạt động nếu bạn muốn làm cho các tập tin tạo ra trông mát mẻ.

                int num = 1;
                var spin = new ConsoleSpinner();
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write("");
                while (true)
                {
                    spin.Turn();
                    Console.Write("\r{0} Generating Files ", num);
                    num++;
                }

Và đây là phương pháp mà tôi đã nhận được từ một số câu trả lời dưới đây và sửa đổi nó

public class ConsoleSpinner
    {
        int counter;

        public void Turn()
        {
            counter++;
            switch (counter % 4)
            {
                case 0: Console.Write("."); counter = 0; break;
                case 1: Console.Write(".."); break;
                case 2: Console.Write("..."); break;
                case 3: Console.Write("...."); break;
                case 4: Console.Write("\r"); break;
            }
            Thread.Sleep(100);
            Console.SetCursorPosition(23, Console.CursorTop);
        }
    }

0

Đây là một cái khác: D

class Program
{
    static void Main(string[] args)
    {
        Console.Write("Working... ");
        int spinIndex = 0;
        while (true)
        {
            // obfuscate FTW! Let's hope overflow is disabled or testers are impatient
            Console.Write("\b" + @"/-\|"[(spinIndex++) & 3]);
        }
    }
}

0

Nếu bạn muốn cập nhật một dòng, nhưng thông tin quá dài để hiển thị trên một dòng, nó có thể cần một số dòng mới. Tôi đã gặp phải vấn đề này và dưới đây là một cách để giải quyết vấn đề này.

public class DumpOutPutInforInSameLine
{

    //content show in how many lines
    int TotalLine = 0;

    //start cursor line
    int cursorTop = 0;

    // use to set  character number show in one line
    int OneLineCharNum = 75;

    public void DumpInformation(string content)
    {
        OutPutInSameLine(content);
        SetBackSpace();

    }
    static void backspace(int n)
    {
        for (var i = 0; i < n; ++i)
            Console.Write("\b \b");
    }

    public  void SetBackSpace()
    {

        if (TotalLine == 0)
        {
            backspace(OneLineCharNum);
        }
        else
        {
            TotalLine--;
            while (TotalLine >= 0)
            {
                backspace(OneLineCharNum);
                TotalLine--;
                if (TotalLine >= 0)
                {
                    Console.SetCursorPosition(OneLineCharNum, cursorTop + TotalLine);
                }
            }
        }

    }

    private void OutPutInSameLine(string content)
    {
        //Console.WriteLine(TotalNum);

        cursorTop = Console.CursorTop;

        TotalLine = content.Length / OneLineCharNum;

        if (content.Length % OneLineCharNum > 0)
        {
            TotalLine++;

        }

        if (TotalLine == 0)
        {
            Console.Write("{0}", content);

            return;

        }

        int i = 0;
        while (i < TotalLine)
        {
            int cNum = i * OneLineCharNum;
            if (i < TotalLine - 1)
            {
                Console.WriteLine("{0}", content.Substring(cNum, OneLineCharNum));
            }
            else
            {
                Console.Write("{0}", content.Substring(cNum, content.Length - cNum));
            }
            i++;

        }
    }

}
class Program
{
    static void Main(string[] args)
    {

        DumpOutPutInforInSameLine outPutInSameLine = new DumpOutPutInforInSameLine();

        outPutInSameLine.DumpInformation("");
        outPutInSameLine.DumpInformation("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");


        outPutInSameLine.DumpInformation("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
        outPutInSameLine.DumpInformation("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");

        //need several lines
        outPutInSameLine.DumpInformation("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
        outPutInSameLine.DumpInformation("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");

        outPutInSameLine.DumpInformation("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
        outPutInSameLine.DumpInformation("bbbbbbbbbbbbbbbbbbbbbbbbbbb");

    }
}

0

Tôi đã tìm kiếm giải pháp tương tự trong vb.net và tôi đã tìm thấy giải pháp này và nó thật tuyệt.

tuy nhiên như @JohnOdom đã đề xuất một cách tốt hơn để xử lý không gian trống nếu trước đó lớn hơn không gian hiện tại ..

tôi tạo một chức năng trong vb.net và nghĩ rằng ai đó có thể được giúp đỡ ..

đây là mã của tôi:

Private Sub sPrintStatus(strTextToPrint As String, Optional boolIsNewLine As Boolean = False)
    REM intLastLength is declared as public variable on global scope like below
    REM intLastLength As Integer
    If boolIsNewLine = True Then
        intLastLength = 0
    End If
    If intLastLength > strTextToPrint.Length Then
        Console.Write(Convert.ToChar(13) & strTextToPrint.PadRight(strTextToPrint.Length + (intLastLength - strTextToPrint.Length), Convert.ToChar(" ")))
    Else
        Console.Write(Convert.ToChar(13) & strTextToPrint)
    End If
    intLastLength = strTextToPrint.Length
End Sub

Tại đây bạn có thể sử dụng tính năng VB của biến tĩnh cục bộ : Static intLastLength As Integer.
Đánh dấu

0

Tôi đang thực hiện tìm kiếm này để xem liệu giải pháp tôi viết có thể được tối ưu hóa cho tốc độ hay không. Điều tôi muốn là đồng hồ đếm ngược, không chỉ cập nhật dòng hiện tại. Đây là những gì tôi nghĩ ra. Có thể hữu ích cho ai đó

            int sleepTime = 5 * 60;    // 5 minutes

            for (int secondsRemaining = sleepTime; secondsRemaining > 0; secondsRemaining --)
            {
                double minutesPrecise = secondsRemaining / 60;
                double minutesRounded = Math.Round(minutesPrecise, 0);
                int seconds = Convert.ToInt32((minutesRounded * 60) - secondsRemaining);
                Console.Write($"\rProcess will resume in {minutesRounded}:{String.Format("{0:D2}", -seconds)} ");
                Thread.Sleep(1000);
            }
            Console.WriteLine("");

0

Lấy cảm hứng từ @ E.Lahu Solution, việc thực hiện một tiến trình thanh với tỷ lệ phần trăm.

public class ConsoleSpinner
{
    private int _counter;

    public void Turn(Color color, int max, string prefix = "Completed", string symbol = "■",int position = 0)
    {
        Console.SetCursorPosition(0, position);
        Console.Write($"{prefix} {ComputeSpinner(_counter, max, symbol)}", color);
        _counter = _counter == max ? 0 : _counter + 1;
    }

    public string ComputeSpinner(int nmb, int max, string symbol)
    {
        var spinner = new StringBuilder();
        if (nmb == 0)
            return "\r ";

        spinner.Append($"[{nmb}%] [");
        for (var i = 0; i < max; i++)
        {
            spinner.Append(i < nmb ? symbol : ".");
        }

        spinner.Append("]");
        return spinner.ToString();
    }
}


public static void Main(string[] args)
    {
        var progressBar= new ConsoleSpinner();
        for (int i = 0; i < 1000; i++)
        {
            progressBar.Turn(Color.Aqua,100);
            Thread.Sleep(1000);
        }
    }

0

Đây là câu trả lời của tôi về soosh và 0xA3. Nó có thể cập nhật bảng điều khiển với thông điệp người dùng trong khi cập nhật spinner và có chỉ báo thời gian trôi qua.

public class ConsoleSpiner : IDisposable
{
    private static readonly string INDICATOR = "/-\\|";
    private static readonly string MASK = "\r{0} {1:c} {2}";
    int counter;
    Timer timer;
    string message;

    public ConsoleSpiner() {
        counter = 0;
        timer = new Timer(200);
        timer.Elapsed += TimerTick;
    }

    public void Start() {
        timer.Start();
    }

    public void Stop() {
        timer.Stop();
        counter = 0;
    }

    public string Message {
        get { return message; }
        set { message = value; }
    }

    private void TimerTick(object sender, ElapsedEventArgs e) {
        Turn();
    }

    private void Turn() {
        counter++;
        var elapsed = TimeSpan.FromMilliseconds(counter * 200);
        Console.Write(MASK, INDICATOR[counter % 4], elapsed, this.Message);
    }

    public void Dispose() {
        Stop();
        timer.Elapsed -= TimerTick;
        this.timer.Dispose();
    }
}

sử dụng là một cái gì đó như thế này:

class Program
{
    static void Main(string[] args)
    {
        using (var spinner = new ConsoleSpiner())
        {
            spinner.Start();
            spinner.Message = "About to do some heavy staff :-)"
            DoWork();
            spinner.Message = "Now processing other staff".
            OtherWork();
            spinner.Stop();
        }
        Console.WriteLine("COMPLETED!!!!!\nPress any key to exit.");

    }
}

-1

Các SetCursorPositionphương pháp làm việc trong kịch bản đa luồng, nơi hai phương pháp khác không

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.