1

我一直在試圖讓這個小的IRC程序工作,但由於某些原因,我遇到了VS和跨線程問題。我不確定我是不是以正確的方式或方式來做這件事。以下是導致問題的部分。C#跨線程。 IRC流線程到主UI線程

主線:

public partial class MainUI : Form 
{ 
    private static IRC irc = new IRC(); 
    public MainUI() 
    { 
     InitializeComponent(); 
    } 
    public static void StartIRC() 
    { 
     irc.Start(); 
    } 
} 

IRC主題:

class IRC 
{ 
    private Thread ircThread; 
    private bool _running = true; 
    private NetworkStream stream; 
    private StreamWriter writer; 
    private StreamReader reader; 
    private TcpClient irc; 
    public IRC(){ 
     ircThread = new Thread(new ThreadStart(Run)); 
     ircThread.IsBackground = true; 
    } 
    public void Run(){ 
     while (_running) { 
      parseInStream(reader.ReadLine()); 
     } 
    } 
    public void Start() 
    { 
     ircThread.Start(); 
    } 
    private void parseInStream(String inText) 
    { 
     String[] text = inText.Split(' '); 
     String name; 
     String message; 
     if (text[1].Equals("PRIVMSG")) { 
      name = capsFirstChar(getUser(inText)); 
      message = inText.Substring(inText.IndexOf(":", 1) + 1); 
      sendToChatBox(capsFirstChar(name) + ": " + message, Color.Black); 
     } 
     else if (text[1].Equals("JOIN")) { 
      name = getUser(inText); 
      sendToChatBox(capsFirstChar(name) + " has joined the channel.", Color.LimeGreen); 
     } 
     else if (text[1].Equals("PART")) { 
      name = getUser(inText); 
      sendToChatBox(capsFirstChar(name) + " has left the channel.", Color.Red); 
     } 
    } 
    public void sendToChatBox(String text, Color color) 
    {  
     //Trying to send the text to the chatbox on the MainUI 
     //Works if the MainUI.Designer.cs file has it set to static 

     if (MainUI.txtMainChat.InvokeRequired) { 
      MainUI.txtMainChat.Invoke((MethodInvoker)delegate() { 
       sendToChatBox(text, color); 
      }); 
     } 
     else { 
      MainUI.txtMainChat.SelectionColor = color; 
      MainUI.txtMainChat.AppendText(text); 
     } 
    } 
    private String getUser(String msg) 
    { 
     String[] split = msg.Split('!'); 
     user = split[0].Substring(1); 
     return capsFirstChar(user); 
    } 
    private String capsFirstChar(String text) 
    { 
     return char.ToUpper(text[0]) + text.Substring(1).ToLower(); 
    } 
} 

我能得到它的唯一途徑是,如果我進入MainUI.Designer.cs文件,更改文本框靜態,然後從this.txtMainChatto MainUI.txtMainChat更改一切。

我的主要問題是,當我在視覺方面進行任何更改時,所有標記爲靜態的東西或名爲MainUI的東西都將被刪除。我試圖弄清楚我需要做些什麼來防止這種情況發生。我是正確的做法,還是有更好的辦法?我嘗試過使用後臺工作器,但由於某種原因,它使用了大量的處理能力來工作。

我環顧網絡,似乎無法找出如何可能與我的設置有關。我看到人們從主線程調用一個線程,然後將主線程中的東西發送到它調用的線程,而不是其他方式。沒有其他任何東西被寫入文本框,因此兩個線程同時使用時不會有問題。

+1

該代碼看起來都捆綁在一起的所有方式,這增加了混淆。我將這裏的代碼分成類似MVVM的東西,或者至少改變你的UI和處理類。 例如,您可以讓IRC類讀取行和調用事件,然後更新自身的MainForm代碼(儘管imo仍然是一個糟糕的選擇,並且最好引入ViewModel類的類)。 您使用的是什麼C#和.Net版本?如果您能夠使用TPL和異步/等待模式(C#5/.Net 4.5級別),則可能會得到更好的控制。 – zaitsman

+0

在VS 2013的v4.5。這是我第一個實際的Windows應用程序,所以我知道它不是最好的形式。 – JustinCase

回答

1

每當您在設計器中更改UI時,都會重建您的設計器文件。

您需要將MainUi傳遞給IRC類,或者使用接口(最佳選項)爲其提供抽象。

public interface IMainUI 
{ 
    void AddText(string text, Color color); 
    void UiThread(Action code); 
} 

public class MainUI : IMainUI 
{ 
    // Whatever else 
    public void AddText(string text, Color color) 
    { 
     UiThread(() => 
     { 
      // Same code that was in your Irc.SendToChatBox method.  
     }); 
    } 

    public void UiThread(Action code) 
    { 
     if (InvokeRequired) 
     { 
      BeginInvoke(code); 
      return; 
     } 
     code.Invoke(); 
    } 
} 

public class IRC 
{ 
    IMainUI _mainUi; 
    //Other properties, and fields  

    public IRC(IMainUI mainUi) 
    { 
     this._mainUi = mainUi; 

     // Other constructor stuff. 
    } 

    // Other logic and methods 
} 
1

在我的主UI線程中,我傳遞了「this」,所以我可以從我的IRC類引用主窗口。 MainUI.txtMainChat

irc = new IRC(this); 

然後在我的IRC類

MainUI main; 
public IRC(MainUI main){ 
    this.main = main; 
    ircThread = new Thread(new ThreadStart(Run)); 
    ircThread.IsBackground = true; 
} 

然後,我能夠改變

//MainUI.txtMainChat to 
main.txtMainChat 

像卡梅倫說,雖然我知道有人告訴我,這是不是最好的方法它讓我開始了。