C#中的线程和GUI元素

时间:2009-02-11 03:05:58

标签: c# multithreading user-interface

我正在尝试创建一个基本的IRC客户端...但我的问题是让文本显示在RTF框中而不会滞后

我决定使用线程,我想更新一个线程中的RTF框,但我不能因为它给我关于RTF框元素不是静态的错误?

任何见解?如果你们想要它我会粘贴代码


好的,这里是代码(编辑凹凸?)

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)
        {

        }
    }
}


一些方法是空白的,一些代码可以清理,但我想先完成这个...也是,由设置窗口的视觉工作室生成的代码

6 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:1)

我相信您使用的是Windows窗体。查看有关它的this文本,在使线程直接访问表单元素之前,您需要注意一些注释。

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

答案 2 :(得分:1)

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

使用此技术:

    来自您的线程的
  • 引发事件以更新RTF(带有所需的文本等数据)
  • GUI线程上的
  • 使用以下内容:
  • 使用“InvokeRequired”属性来验证是否来自GUI线程
  • 使用Invoke方法(您需要一个委托)

BeginInvoke也可以,但唯一的问题是它并不能保证立即启动(它使用线程池)。我更喜欢使用Invoke方法。

答案 3 :(得分:1)

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

不是因为有一个单独的工作线程是一个坏主意,由于性能原因,你需要多个线程似乎很奇怪。似乎对于像IRC客户端一样简单的东西,你应该能够在一个线程上做所有事情,而不会有任何UI缓慢。也许你可以发布一些代码,以便我们可以看到问题的根源是什么?

答案 4 :(得分:0)

RichTextBox位于UI线程上,因此除非您在UI线程上,否则您将无法访问RichTextBox。你是如何加载内容的?内容有多大?滞后来自加载内容还是解析它的RTF框?

答案 5 :(得分:0)

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

无论如何,这是一个非常错误的方法,因为UI元素只能从UI线程更新,否则您将获得跨线程操作异常。因此,您需要对UI线程上的set-text方法执行Invoke(),这最终会“滞后”。

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