J'aimerais réaliser quelque chose comme ceci:
Time consuming operation...OK
Another time consuming operation...
And another one, but it completed, so...OK
J'ai affiché 3 lignes de texte, chacune liée à un fil qui peut se terminer tôt ou tard. Mais si le second est terminé plus tard que le troisième, j'obtiendra quelque chose comme ceci:
Time consuming operation...OK
Another time consuming operation...
And another one, but it completed, so...OKOK
Ce qui est bien sûr inacceptable. Je sais comment revenir dans la ligne actuelle, mais y a-t-il un moyen de remonter? Je jure que je l'ai vu quelque part, même si cela pourrait être une console Linux :)
Oublie. Voir le gestionnaire de fichiers distant! Cela fonctionne dans la console Windows, même dans PowerShell! Comment faire quelque chose comme ça? Et la partie la plus cool est qu'elle restaure l'état de la console après la sortie. Alors peut-être devrais-je demander: comment accéder directement au tampon de la console? Je suppose que je vais avoir besoin de code natif pour faire l'affaire, mais peut-être y a-t-il un autre moyen? J'ai pensé à effacer la console à chaque mise à jour, mais cela semble excessif. Ou peut-être que ce n'est pas? Cela va-t-il clignoter?
Vous pouvez déplacer le curseur où vous voulez: Console.SetCursorPosition ou utilisez Console.CursorTop .
Console.SetCursorPosition(0, Console.CursorTop -1);
Console.WriteLine("Over previous line!!!");
Utilisez un retour chariot. Cet exemple imprime une seule ligne et remplace ce qui était auparavant.
Console.WriteLine();
for (int i = 0; i <= 100; i++)
{
System.Threading.Thread.Sleep(10);
Console.Write("\x000DProgress: " + i);
}
Cela fonctionne tant que toutes vos chaînes sont moins de 80 colonnes (ou quel que soit le tampon de votre terminal).
Remarque: la réponse suivante a été modifiée à l'origine dans la question par le PO.
Voici une solution complète avec démo:
using System;
using System.Collections.Generic;
using System.Threading;
namespace PowerConsole {
internal class Containers {
internal struct Container {
public int Id;
public int X;
public int Y;
public string Content;
}
public static List<Container> Items = new List<Container>();
private static int Identity = 0;
public static int Add(string text) {
var c = new Container();
c.Id = Identity++;
c.X = Console.CursorLeft;
c.Y = Console.CursorTop;
c.Content = text;
Console.Write(text);
Items.Add(c);
return c.Id;
}
public static void Remove(int id) {
Items.RemoveAt(id);
}
public static void Replace(int id, string text) {
int x = Console.CursorLeft, y = Console.CursorTop;
Container c = Items[id];
Console.MoveBufferArea(
c.X + c.Content.Length, c.Y,
Console.BufferWidth - c.X - text.Length, 1,
c.X + text.Length, c.Y
);
Console.CursorLeft = c.X;
Console.CursorTop = c.Y;
Console.Write(text);
c.Content = text;
Console.CursorLeft = x;
Console.CursorTop = y;
}
public static void Clear() {
Items.Clear();
Identity = 0;
}
}
internal class Program {
private static List<Thread> Threads = new List<Thread>();
private static void Main(string[] args) {
Console.WriteLine("So we have some threads:\r\n");
int i, id;
Random r = new Random();
for (i = 0; i < 10; i++) {
Console.Write("Starting thread " + i + "...[");
id = Containers.Add("?");
Console.WriteLine("]");
Thread t = new Thread((object data) => {
Thread.Sleep(r.Next(5000) + 100);
Console.ForegroundColor = ConsoleColor.Green;
Containers.Replace((int)data, "DONE");
Console.ResetColor();
});
Threads.Add(t);
}
Console.WriteLine("\n\"But will it blend?\"...");
Console.ReadKey(true);
i = 0;
Threads.ForEach(t => t.Start(i++));
Threads.ForEach(t => t.Join());
Console.WriteLine("\r\nVoila.");
Console.ReadKey(true);
}
}
}