最近,我开始使用VB.Net开发基于多线程控制台的应用程序,并且遇到(可解释的)错误。程序本身是一个服务器,它从不同线程的外部应用程序接收套接字连接。我还有一个单独的线程,它只是等待用户使用console.readline在应用程序中输入文本(这样就可以输入服务器命令,如HELP或STATUS)。
问题是程序从不同的套接字线程输出消息,如果我正在键入命令,它会被分解。如果我输入命令“status”,它将按预期工作,但是对于输入命令的用户,它会被分解,并且他们可能无法看到他们是否输入了错误的命令。例如:
staNew客户连接。
土族
我知道为什么会发生这种情况,但我很好奇是否有一个简单的解决办法来阻止它(不必在输入期间暂停其他线程)或者可能更简单的方法来允许输入控制台命令而不是移动了额外的应用程序输出。
答案 0 :(得分:1)
一些建议:
tail
或类似的东西,a或
应用程序和用户可以同时打开两个应用程序,一个显示
消息和其他交互式运行命令并查看输出。答案 1 :(得分:1)
C Sharp等价物
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Timers;
namespace testconsole
{
class Program
{
private static bool Running = true;
private static string Command = "";
static void Main( string[] args )
{
while ( Running )
{
ReadInput();
}//running
}//main-----------------------------------------
static void ReadInput()
{
ConsoleKeyInfo cki;
cki = Console.ReadKey();
if ( cki.Key == ConsoleKey.Escape )
{
Command = "";
}
else if (cki.Key == ConsoleKey.Backspace)
{
ClearConsole();
if ( Command.Length > 0 )
{
Command = Command.Substring( 0, Command.Length - 1 );
}
Console.CursorLeft = 0;
Console.Write( Command );
}
else if ( cki.Key == ConsoleKey.Enter )
{
Console.CursorLeft = 0;
ClearConsole();
string TempCommand = Command;
TextOut( Command );
Command = "";
//process tempcommand
if ( TempCommand == "quit")
{
Running = false;
}
if ( TempCommand == "test" )
{
TextOut("this is a test");
}
}
else
{
Command += cki.KeyChar;
Console.CursorLeft = 0;
Console.Write( Command );
}
}//ReadInput-----------------------------------------
static void ClearConsole()
{
for ( int i = 0; i < Command.Length; i++ )
{
Console.Write( " " );
}
}//ClearConsole-----------------------------------------
static void TextOut( string Message )
{
if (Command != "")
{
ClearConsole();
}
Console.CursorLeft = 0;
Console.WriteLine( Message );
if ( Message != Command )
{
Console.Write( Command );
}
}//TextOut-----------------------------------------
}//program
}//namespace
答案 2 :(得分:1)
这是一个稍微不同的版本,支持readlines上的前缀,并打包到它自己的类中以供重用。它还使用StringBuilder而不是字符串作为readline。
public static class Console2
{
private static bool _isReading;
private static string _currentPrefix;
private static readonly StringBuilder CurrentReadLine = new StringBuilder();
public static string ReadLine(string prefix = null)
{
_currentPrefix = prefix;
_isReading = true;
Console.Write(prefix);
while (true)
{
ConsoleKeyInfo cki;
cki = Console.ReadKey();
if (cki.Key == ConsoleKey.Escape)
{
CurrentReadLine.Clear();
}
else if (cki.Key == ConsoleKey.Backspace)
{
if (CurrentReadLine.Length > 0)
{
CurrentReadLine.Length--;
}
ClearConsole();
Console.Write(prefix + CurrentReadLine);
}
else if (cki.Key == ConsoleKey.Enter)
{
Console.WriteLine();
var result = CurrentReadLine.ToString();
CurrentReadLine.Clear();
_isReading = false;
return result;
}
else
{
CurrentReadLine.Append(cki.KeyChar);
}
}
}
static void ClearConsole()
{
var length = Console.CursorLeft;
Console.CursorLeft = 0;
for (int i = 0; i <= length; i++)
{
Console.Write(" ");
}
Console.CursorLeft = 0;
}
public static void WriteLine(string format, params object[] args)
{
ClearConsole();
Console.WriteLine(format, args);
if (_isReading)
{
Console.Write(_currentPrefix + CurrentReadLine);
}
}
}
答案 3 :(得分:0)
使用集中式记录器并在用户输入时禁用输出。
答案 4 :(得分:0)
我知道这个问题大多是美学的,但这样的事情让我很烦。我讨厌回答我自己的问题,但实际上我根据其他人的一些意见想出了一个相当不错的解决方案。我将附上一个代码示例,以防将来有人想要做类似的事情。我知道可能有更好的方法来做到这一点,但这就是我所做的。
基本上我没有使用每个线程的console.writeline,而是创建了一个新的子例程(TextOut),后面有一些逻辑。我还更新了我的输入线程,将每个char读入共享字符串,而不是使用console.readline()。这是代码:
Private command As String = ""
Private Sub ConsoleInput()
Dim cki As ConsoleKeyInfo
cki = Console.ReadKey()
If cki.Key = ConsoleKey.Escape Then
command = "" 'Clear command
ElseIf cki.Key = ConsoleKey.Backspace Then
If Len(command) > 0 Then 'Make sure you don't go out of bounds
For i As Integer = 0 To Len(command)
Console.Write(" ") 'Clear output since new string will be shorter
Next
command = Left(command, Len(command) - 1) 'Shorten command by 1 char
End If
Console.CursorLeft = 0 'Set the cursor to the beginning of the line
Console.Write(command) 'Write the command to the screen
ElseIf cki.Key = ConsoleKey.Enter Then 'Command has been submitted, start checking
Console.CursorLeft = 0 'Set the cursor to the beginning of the line
For i As Integer = 0 To Len(command)
Console.Write(" ") 'Clear output from command (hides the executed command)
Next
Dim tempCMD As String = command
command = ""
'If/then statements for validating command goes here
command = "" 'Clear command to allow new input
Else
command += cki.KeyChar 'Add char to command string
Console.CursorLeft = 0 'Set the cursor to the beginning of the line
Console.Write(command) 'Write the command to the screen
End If
ConsoleInput() 'Loop for more input
End Sub
Sub TextOut(ByVal message As String)
If command <> "" Then
For i As Integer = 0 To Len(command)
Console.Write(" ") 'Clears output in case output is shorter than current command
Next
Console.CursorLeft = 0 'Sets cursor to beginning of row
End If
Console.WriteLine(message) 'Writes the current message to the screen
If message <> command Then
Console.Write(command) 'Writes the command back to the screen
End If
End Sub