2

while(true) ループと Console.ReadLine を介してユーザーから継続的にコマンドを取得する C# で記述されたアプリケーションがあります。

また、コンソールを介して報告するさまざまなバックグラウンド操作もあります。次の簡単な例をご覧ください。

class Program
{  
        static void Main(string[] args)
        {
            new Messager(1000 * 2.5f);
            new Messager(1000 * 3);
            while (true)
            {
                Console.ReadLine();
            }
        }
}

public class Messager
{
    Timer Timer;

    public Messager(double interval)
    {
        this.Timer = new Timer(interval);
        this.Timer.Elapsed += (sender, e) =>
        {
            Console.WriteLine("message from " + this.Timer.Interval);
        };
        this.Timer.Start();
    }
}

問題は、コマンドを入力し、Enter を押す前に Messager がレポートを返すと、Messager からのメッセージが現在の行に追加され、カーソルが次の行に配置されることです。このスクリーンショットを参照してください。

問題

ご想像のとおり、私はそれを望んでいません。コマンドの現在の入力が常に最後の行に残り、すべてのメッセージがその行の上に配置されるようにします。このようなアプリケーションに期待するとおりです。どうすればそれを達成できますか?

4

3 に答える 3

5

これを行うのは非常に困難です。すべてのスレッドが呼び出さなければならない独自のコンソール入出力メソッドを作成することになります。どのスレッドも連携しない場合、正しく動作しません。ただし、コンソール API を使用することは可能です。

基本的な考え方は、テキストが最後の行に流れて自動的にスクロールするのではなく、共通の出力関数をコンソール画面バッファーに書き込み、コードでバッファーをスクロールすることです。思い出したように、改行やその他の制御文字の出力を解析し、正しく処理する必要があります。

最後の行で使用Console.ReadLineすることで回避できる場合がありますが、そうすると、ユーザーが 1 行に収まりきらないほど多くのテキストを入力すると問題が発生する可能性があります。また、ユーザーが行末で Enter キーを押すと、上にスクロールする可能性があります。この状況では、生のコンソール入力を使用するのがおそらく最善です。

Windows コンソールに慣れる必要があります。

事前に注意してください:それは大変な作業です。そして、おそらく努力する価値はありません。

于 2013-08-05T14:14:09.523 に答える
0

ただのアイデア。Console.CursorTopプロパティとプロパティを使用できConsole.CursorLeftます。

class Program
{
    static void Main(string[] args)
    {
        new Messager(1000 * 2.5f);
        new Messager(1000 * 3);

        while (true)
        {
            Console.CursorTop = 0;
            Console.ReadLine();
        }
    }
}

public class Messager
{
    Timer Timer;

    static int position = 1;

    public Messager(double interval)
    {
        this.Timer = new Timer(interval);

        this.Timer.Elapsed += (sender, e) =>
        {
            lock (this)
            {
                var cursorLeft = Console.CursorLeft;
                Console.CursorLeft = 0;
                Console.CursorTop = position++;
                Console.WriteLine("message from " + this.Timer.Interval);
                Console.CursorTop = 0;
                Console.CursorLeft = cursorLeft;
            }
        };

        this.Timer.Start();
    }
}
于 2013-08-05T14:16:50.577 に答える