2009-02-11 75 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遲鈍。也許你可以發佈一些代碼,以便我們可以看到問題的根源是什麼?