【问题标题】:Threading and GUI elements in C#C# 中的线程和 GUI 元素
【发布时间】:2009-02-11 03:05:57
【问题描述】:

我正在尝试制作一个基本的 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)
        {

        }
    }
}


有些方法是空白的,有些代码可以清理,但我想先完成这件事……另外,还有 Visual Studio 生成的设置窗口的代码

【问题讨论】:

    标签: c# multithreading user-interface


    【解决方案1】:

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

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

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

    【讨论】:

    • 你还需要给 lambda 表达式一个合适的委托类型来转换。
    • 谢谢,我担心我可能需要这样做,但我手边没有 VS2008 的副本。
    • 那么正确的方法是什么
    • 更新后的代码应该可以工作,如果不行请告诉我。
    • 好吧,我刮掉了那个窗口类并重新开始......但我遇到了错误: Thread t = new Thread(new ThreadStart(update));私人无效更新(){ this.richTextBox1.BeginInvoke((MethodInvoker)(()=> this.richTextBox1.Text =“foo”)); }
    【解决方案2】:

    我相信您正在使用 Windows 窗体。查看this 的相关文字,在创建线程直接访问表单元素之前,您必须注意一些注意事项。

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

    【讨论】:

      【解决方案3】:

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

      使用这种技术:

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

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            【解决方案6】:

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

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

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

            【讨论】:

              猜你喜欢
              • 2021-05-29
              • 1970-01-01
              • 1970-01-01
              • 2012-11-19
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多