1

我有这个问题。我需要能够从 OnMessage 中将传入消息附加到 txtConsole,但我收到了 Illegal Cross Thread 错误。我该如何解决这个问题?我在 C# 方面非常基础,所以一些带有解释的代码(没有伪代码)会有所帮助。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Apache.NMS;
using Apache.NMS.Util;

namespace WindowsFormsApplication1
{
    public partial class frmConsole : Form
    {


        public frmConsole()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, System.EventArgs e)
        { }

        public void cmdConnect_Click(object sender, EventArgs e)
        {
            // Output to the user that the connection is being set up
            txtConsole.AppendText(Environment.NewLine + "Setting up connection...");
            // Define the feed URL
            IConnectionFactory factory = new NMSConnectionFactory(new Uri("stomp:tcp://datafeeds.networkrail.co.uk:61618"));
            // Define the credentials
            IConnection connection = factory.CreateConnection("REDACTED", "REDACTED");
            // Create the session
            ISession session = connection.CreateSession();
            // Specify which feed - we want TRAIN_MVT_ALL_TOC to listen for all train movements
            IDestination destination = session.GetDestination("topic://" + "TRAIN_MVT_ALL_TOC");
            // Let the end user know where we will be subscribing to
            txtConsole.AppendText(Environment.NewLine + "Will attempt subscription to " + destination);
            // Create a consumer for the feed
            IMessageConsumer consumer = session.CreateConsumer(destination);
            // Let the end user know we are about to connect...
            txtConsole.AppendText(Environment.NewLine + "Connecting...");
            // Connection details are now all set up. Start the connection...
            connection.Start();
            // Check we are connected
            if (connection.IsStarted == false)
            {
                txtConsole.AppendText(Environment.NewLine + "Connection closed.");
                connection.Close();
            }
            // Now we need to handle messages using a MessageListener where we pass it to the OnMessage void.
            consumer.Listener += new MessageListener(OnMessage);

            txtConsole.AppendText(Environment.NewLine + "Connection established. Waiting for messages...");


            // End of void
        }


        public void OnMessage(IMessage message)
        {

            ITextMessage msg = (ITextMessage)message;
            message.Acknowledge();
            txtConsole.AppendText(Environment.NewLine + msg.Text);
        }
    }
}
4

3 回答 3

0

您收到该错误的原因是您尝试从非 UI 线程更新 UI 元素。您可以调用控件的Invoke方法来强制它在 UI 线程上运行。

public void OnMessage(IMessage message)
{ 
    ITextMessage msg = (ITextMessage)message;
    message.Acknowledge();

    if (txtConsole.InvokeRequired)
    {
        txtConsole.Invoke(new Action(() =>
          {
             txtConsole.AppendText(Environment.NewLine + msg.Text);
          }));
    }
    else
    {
        txtConsole.AppendText(Environment.NewLine + msg.Text);
    }
}
于 2013-04-01T17:37:51.760 回答
0

当您尝试从另一个不同的线程访问其他线程(例如,UI 线程)时,会出现该异常。

你可以解决那个调用

Dispatcher.BeginInvoke(() => delegate{// Here the code});

从你想要的任何线程

于 2013-04-01T17:38:57.077 回答
0

如何正确处理跨线程事件并使用 BeginInvoke 和 BackgroundWorker 更新标签

跨线程 UI 控制访问

只需txtConsole.AppendText在方法OnMessage中替换为

txtConsole.Invoke((Action)(() => txtConsole.AppendText(Environment.NewLine + msg.Text)));
于 2013-04-01T17:39:22.507 回答