我已经找到了解决问题的方法,但我还没找到。
我正在编写一个将连接到irc服务器的机器人。我希望用户可以访问win表单窗口,在该窗口中可以输入服务器,频道等。
这是窗口:
我已将控制台输出设置为使用主程序中的代码更新我的文本框。有了这个,我将所有来自子类的文本都放到我的文本框中。
static class Program
{
private static Form1 Form1;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
using (var consoleWriter = new ConsoleWriter())
{
consoleWriter.WriteLineEvent += consoleWriter_WriteLineEvent;
Console.SetOut(consoleWriter);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 = new Form1();
Application.Run(Form1);
}
}
static void consoleWriter_WriteLineEvent(object sender, ConsoleWriterEventArgs msg)
{
var message = msg.Value;
Form1.statusTextBox.AppendText(message + "\r\n");
}
}
public class ConsoleWriter : TextWriter
{
public override Encoding Encoding { get { return Encoding.UTF8; } }
public override void Write(string value)
{
if (WriteEvent != null) WriteEvent(this, new ConsoleWriterEventArgs(value));
base.Write(value);
}
public override void WriteLine(string value)
{
if (WriteLineEvent != null) WriteLineEvent(this, new ConsoleWriterEventArgs(value));
base.WriteLine(value);
}
public event EventHandler<ConsoleWriterEventArgs> WriteEvent;
public event EventHandler<ConsoleWriterEventArgs> WriteLineEvent;
}
public class ConsoleWriterEventArgs : EventArgs
{
public string Value { get; private set; }
public ConsoleWriterEventArgs(string value)
{
Value = value;
}
}
现在,当我点击“Connect”按钮时,我在Form1中调用它:
gbaIrcBot.Connect(server, null, port, nick, channelList);
在gbaIrcBot.Connect()中,我还有:
private void ReadStream()
{
string inputLine;
while ((inputLine = _streamReader.ReadLine()) != null)
{
var splitInput = inputLine.Split(new[] { ' ' });
if (splitInput.ElementAt(0) == "PING") { Pong(splitInput.ElementAt(1)); continue;}
switch (splitInput.ElementAt(1))
{
case "001": foreach (var channel in ChannelList) JoinChannel(channel); break;
case "PRIVMSG": ProcessPrivMsg(splitInput); break;
case "433": SetNick("AlternativeBOT"); break;
default: Console.WriteLine(inputLine); break;
}
}
}
此方法负责读取irc服务器的所有输入。当我从服务器收到消息时,我将其发送到控制台,该控制台更新Form1中的文本框。它必须是一个无限循环。
如果我不创建一个线程来保持我的UI不被冻结,这一切都很有效。这是一个例子:
当我尝试创建一个线程时,My Form1抛出一个异常,说它是一个跨线程的消息,我不能从外面更新它。
有什么想法解决它?
答案 0 :(得分:0)
必须在UI线程上执行WinForms UI更新。试试这种方法:
答案 1 :(得分:0)
表单上的更新必须在窗口更新线程中完成。
您可以使用BeginInvoke()打包来强制执行此类线程。
更改
Form1.statusTextBox.AppendText(message + "\r\n");
到
Form1.BeginInvoke(() => Form1.statusTextBox.AppendText(message + "\r\n"));