Консоль C #: пишите во время чтения и сохраняйте структуру - PullRequest
4 голосов
/ 23 мая 2009

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

Консоль отображает это, пока я печатаю, и приходит сообщение:

сообщение с сервера
сообщение с сервера
мой msmsg с сервера
перевести на сервер

И я хочу, чтобы это отделяло мое сообщение от сообщений серверов, например так:

сообщение с сервера
сообщение с сервера
сообщение с сервера
мои сообщения на сервер

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

Могу ли я это сделать? И как?

Могу ли я переместить свое сообщение в конец консоли, когда приходит сообщение с сервера?

Ответы [ 4 ]

1 голос
/ 23 мая 2009

Вам нужно использовать lock на некоторых object, чтобы остановить оба потока с помощью консоли одновременно. Объявите что-то вроде этого:

public static class ThreadSafeConsole
{
    private static object _lockObject = new object();

    public static void WriteLine(string str)
    {
        lock (_lockObject) 
        {
            Console.WriteLine(str);
        }
    }
}

Теперь звоните ThreadSafeConsole.WriteLine вместо Console.WriteLine.

1 голос
/ 23 мая 2009

Я полагаю, что это на самом деле возможно с помощью стандартного API консоли .NET, используя немного хакерства. Что вам нужно сделать, это создать асинхронный метод Read / ReadLine (который, я полагаю, вы уже сделали, судя по вашему сообщению) и разрешить его отмену, как только поступят новые данные. Я собираюсь предположить, что вы отправляете входные данные построчно. Псевдокод для «нового обработчика данных» может выглядеть примерно так:

Save the current input buffer.
Cancel the current asynchronous read.
Reset the cursor position to the end of the last writing of new data.
Output the new data.
Save the cursor position.
Restart the asynchronous read event.

В частности, вам нужно возиться со свойствами Console.CursorLeft и Console.CursorTop . Возможно, вам удастся избежать некоторых хакерских атак, напрямую взаимодействуя с консольными функциями Win32 API, но, возможно, это не стоит беспокоиться.

Надеюсь, это поможет.

1 голос
/ 23 мая 2009

Вы не можете сделать это напрямую через BCL в C #. Однако есть две основные альтернативы.

1) Превратите это в приложение с графическим интерфейсом и получите отдельные области ввода / вывода. Это наиболее «чистый» вариант из пользовательского POV, но для него требуется приложение с графическим интерфейсом вместо консольного.

2) P / Вызывать в консольный API напрямую. Это дает вам полный контроль над видом консоли, точка за точкой. См. SetConsoleCursorPosition и WriteConsole и т. Д.

0 голосов
/ 23 мая 2009

Если я вас правильно понимаю, вам нужно будет определить, каково начало и конец «ввода в консоль» для вашего приложения, чтобы вы могли по-прежнему блокировать объект, пока это происходит, и не вставлять сообщения из поток слушателя в ваш набранный текст.

public static Object consoleLock = new Object();
public static void Main(string[] args)
{
    lock (consoleLock)
    {
        // now nothing can write to the console (if it's trying to lock onto it)
        Console.WriteLine("Please Input Something");
        // read from console
    }
    // now, your separate thread CAN write to the console - without 
    // interrupting your input process
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...