C#交叉线程。 IRC流线程到主UI线程

时间:2014-07-20 02:52:34

标签: c# multithreading winforms visual-studio-2012 visual-studio-2013

我一直在尝试让这个小小的IRC程序正常工作但由于某种原因我遇到了VS和交叉线程的问题。我不确定我是不是以正确的方式做什么。以下是导致问题的部分。

主线程:

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.txtMainChat更改为MainUI.txtMainChat。

我的主要问题是,当我在视觉方面进行任何更改时,所有标记为静态的内容或名为MainUI的内容都将被删除。我正在试图弄清楚我需要做些什么来防止这种情况发生。我是以正确的方式做到的,还是有更好的方法?我尝试使用后台工作程序,但出于某种原因,它使用了大量处理能力以这种方式工作。

我环顾网络,似乎无法找出与我的设置有什么关系。我看到人们从主线程中调用一个线程,然后将事物从主线程发送到它调用的线程,但不是相反。没有任何其他内容写入文本框,因此两个线程同时使用它不会有问题。

2 个答案:

答案 0 :(得分: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 :(得分:1)

在我的主要UI线程中,我传入了#34;这个"所以我可以从我的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
像卡梅隆说的那样,虽然我知道我被告知这不是最好的办法让我开始。