2009-02-11 85 views
2

我试图做一个基本的IRC客户端...但我的问题越来越离不开它落后

在RTF框中显示的文字我使用的线程解决,我想要更新线程中的RTF框,但我不能因为它给我错误的RTF框元素不是静态的?

有什么见解?我将粘贴代码,如果你们希望它线程和GUI元素


确定这里是代码(做编辑撞?)

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Net.Sockets; 
using System.IO; 
using System.Threading; 
using System.Net; 

namespace IrcClient 
{ 
    public partial class mainWindow : Form 
    { 
     static IRC client; 
     static string newLine, oldLine; 

     public mainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void main() 
     { 

     } 

     private void mainWindow_Load(object sender, EventArgs e) 
     { 
      client = new IRC("irc.freenode.net" ,6667, "jimi__hendrix"); 
      new Thread(new ThreadStart(update)).Start(); 

     } 

     private static void update() 
     { 
      newLine = client.sr.ReadLine(); 

      Thread.Sleep(50); 
     } 

     private void btnSend_Click(object sender, EventArgs e) 
     { 
      client.privmsg(inputBox.Text); 
      messageBox.AppendText(inputBox.Text + "\n"); 
      inputBox.Text = ""; 
     } 

     private void timer1_Tick(object sender, EventArgs e) 
     { 
      if (newLine != oldLine) 
      { 
       messageBox.AppendText(newLine + "\n"); 
       oldLine = newLine; 
      } 
     } 
    } 

    class IRC 
    { 
     TcpClient connection; 
     NetworkStream stream; 
     public StreamWriter sw; 
     public StreamReader sr; 
     string nick; 

     public IRC(string server, int port, string Nick) 
     { 
      try 
      { 
       connection = new TcpClient(server, port); 
       stream = connection.GetStream(); 
       sr = new StreamReader(stream); 
       sw = new StreamWriter(stream); 
       nick = Nick; 
       sw.WriteLine("PASS " + "caruso11"); 
       sw.Flush(); 
       sw.WriteLine("NICK " + nick); 
       sw.Flush(); 
       sw.WriteLine("USER Jimi__Hendrix 8 irc.freenode.net :Jimi__Hendrix"); 
       sw.Flush(); 
      } 

      catch (Exception e) 
      { 
       MessageBox.Show(e.ToString()); 
      } 
     } 

     public void privmsg(string msg) 
     { 
      sw.WriteLine(msg); 
      sw.Flush(); 
     } 

     public void parse(string msg) 
     { 

     } 
    } 
} 


的一些方法是空白的,有些代码可能被清理,但我想先把它完成......还有,视觉工作室生成的代码设置窗口

回答

0

RichTextBox位于UI线程中,因此您无法访问RichTextBox除非你的在UI线程上。你如何加载内容?内容有多大?加载内容或RTF框对内容进行解析会产生滞后吗?

1

我相信你正在使用Windows窗体。查看this关于它的文本,有一些注意事项,在直接访问表单元素之前必须注意。

如果这不完全是您的问题,请详细说明问题。

5

通常,由于Windows的限制,尝试从主线程以外的线程更新控件将不起作用。如果您需要从工作线程调用方法或设置RTF框中的属性,则可能需要使用InvokeBeginInvoke。这可能看起来如下:

void MyThreadMethod() 
{ 
    // stuff 
    this.rtfBox.BeginInvoke((MethodInvoker)(()=> this.rtfBox.Text = "foo")); 
    // stuff 
} 

编辑:正如其他人所指出的,如果这实际上是无法编译由于担心不是静态的控制错误,你可能尝试引用来自静态函数的成员变量,这是非法的。发布代码将有助于缩小问题的范围。

+0

您还需要为lambda表达式转换为适当的委托类型。 – 2009-02-11 07:37:22

+0

谢谢,我担心我可能需要这样做,但我没有VS2008方便的副本。 – Charlie 2009-02-11 18:35:26

1

规则:您不应该从另一个线程访问一个窗口。

使用这种技术:

  • 从你的线程引发一个事件来更新RTF GUI线程上(与所需的文本等数据)
  • 使用以下命令:
  • 使用“InvokeRequired”属性来验证呼叫来自GUI线程或不
  • 使用invoke方法(你将需要为这个委托)

BeginInvoke也可以工作,但唯一的问题是它并不能保证立即开始(它使用线程池)。我宁愿使用Invoke方法。

0

您可能引用了表单的成员变量,而不是静态变量,因此是错误。

无论如何,这是一个相当错误的方法,因为UI元素只能从UI线程更新,否则会得到一个跨线程操作异常。所以你需要对UI线程上的set-text方法进行Invoke()调用,这最终也会“滞后”。

不确定'lagging'是什么意思,你可以尝试让你的父表单双缓冲以减少闪烁。

1

其他人已经提到你遇到的问题是什么,以及如何解决它。

不是说有一个单独的工作线程是一个坏主意,似乎很奇怪,你需要多个线程,因为性能的原因。看起来像IRC客户端那样简单,你应该能够在一个线程上完成所有任务,而不会有任何UI迟钝。也许你可以发布一些代码,以便我们可以看到问题的根源是什么?