Потоки и элементы GUI в C # - PullRequest
2 голосов
/ 11 февраля 2009

я пытаюсь сделать базовый клиент 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 ]

5 голосов
/ 11 февраля 2009

Как правило, попытка обновить элемент управления из потока, отличного от основного потока, не будет работать из-за ограничений Windows. Если вам нужно вызвать метод или установить свойство для поля RTF из рабочего потока, вам, вероятно, потребуется использовать Invoke или BeginInvoke . Это может выглядеть следующим образом:

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

Редактировать : Как отмечают другие, если на самом деле не удается скомпилировать из-за ошибки о том, что элемент управления не является статическим, вы, вероятно, пытаетесь сослаться на переменную-член из статической функции, которая является недопустимой. Размещение кода поможет сузить проблему.

1 голос
/ 11 февраля 2009

Другие уже упоминали, в чем заключается проблема, с которой вы столкнулись, и как ее решить.

Не то, чтобы иметь отдельный рабочий поток - плохая идея, кажется странным, что вам требуется несколько потоков из-за соображений производительности. Похоже, что для столь же простого, как IRC-клиента, вы должны иметь возможность делать все в одном потоке без какой-либо медлительности пользовательского интерфейса. Может быть, вы можете опубликовать некоторый код, чтобы мы могли увидеть, в чем корень проблемы?

1 голос
/ 11 февраля 2009

RULE : Вы не должны получать доступ к одному окну из другого потока.

Используйте эту технику:

  • из вашей ветки поднять событие для обновления RTF (с необходимыми данными и т. Д.)
  • в потоке GUI используйте следующее:
  • используйте свойство "InvokeRequired", чтобы проверить, является ли вызов из потока GUI или нет
  • Используйте метод Invoke (для этого вам понадобится делегат)

BeginInvoke также работает, но единственная проблема в том, что он не гарантирует немедленного запуска (он использует пул потоков). Я предпочитаю использовать метод Invoke вместо этого.

1 голос
/ 11 февраля 2009

Я полагаю, что вы используете Windows Forms. Прочтите этот текст об этом, есть некоторые замечания, которые вы должны позаботиться, прежде чем создавать поток, обращающийся к элементам форм напрямую.

Если это не совсем ваша проблема, пожалуйста, уточните вопрос.

0 голосов
/ 11 февраля 2009

Вы, вероятно, ссылаетесь на переменную-член формы, а не на статическую переменную, поэтому ошибка.

В любом случае, это довольно неправильный подход, поскольку элементы пользовательского интерфейса могут обновляться только из потока пользовательского интерфейса, в противном случае вы получите исключение операции между потоками. Поэтому вам нужно выполнить Invoke () для метода set-text в потоке пользовательского интерфейса, который в конечном итоге тоже будет «запаздывать».

Не уверен, что вы подразумеваете под «отставанием», вы можете попробовать сделать родительскую форму с двойной буферизацией, чтобы уменьшить мерцание.

0 голосов
/ 11 февраля 2009

RichTextBox находится в потоке пользовательского интерфейса, поэтому вы не сможете получить доступ к RichTextBox, если не участвуете в потоке пользовательского интерфейса. Как вы загружаете контент? Насколько большой контент? Задержка при загрузке контента или разборе RTF-окна?

...