0

我在 C# 中创建了两个单独的 Windows 窗体应用程序,它们使用 MSMQ 进行通信。这是它的工作原理,虽然它看起来很简单:

  • App1 向 App2 发送详细信息请求。
  • App2 创建一个事件来打开窗口。
  • App2 打开一个“详细信息”窗口。

我唯一的问题是,当收到消息时,“详细信息”窗口出现后冻结。

当我在一个使用线程的对象中处理 MSMQ 消息处理时,我怀疑问题来自那里......但我没有处理 MSMQ 消息或应用程序部分之间的特定事件处理的经验。

这是我用于 App2 的部分代码:

/*Class declared in the Core namespace*/
public class TaskMessageQueueHandler
{
    public TaskMessageQueueHandler()
    {
        this.Start();
    }

    private Thread m_thread;
    private ManualResetEvent m_signal;
    public event System.EventHandler messageReceived;
    public void Start()
    {
        m_signal = new ManualResetEvent(false);
        m_thread = new Thread(MSMQReceiveLoop);
        m_thread.Start();
    }

    public void Stop()
    {
        m_signal.Set();
    }

    protected virtual void SendEvent(object sender, EventArgs e)
    {
        if (messageReceived != null)
            messageReceived(this.message, e);
    }

    public string message;

    private void MSMQReceiveLoop()
    {
        bool running = true;
        MessageQueue queue = new MessageQueue(@".\Private$\queue1");

        while (running)
        {
            try
            {
                var message = queue.Receive();
                message.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
                this.message = message.Body.ToString();
                string m = this.message;
                SendEvent(m, System.EventArgs.Empty);
                if (m_signal.WaitOne(10))
                {
                    running = false;
                }
            }
            catch
            {
                Console.WriteLine("ERROR");
                running = false;
            }
        }
    }
}

/*Main process, in the Program namespace*/
[...]
Core.TaskMessageQueueHandler tmqh = new Core.TaskMessageQueueHandler();

EventListener el = new EventListener();
tmqh.messageReceived += new System.EventHandler(el.ShowDetails);
[...]
/* Class in the Program namespace */
class EventListener
{
    public void ShowDetails(object sender, EventArgs e)
    {
        int numero = int.Parse(sender as string);
        Details details = new Details(numero);
        details.Show();
    }
}

我哪里做错了?我去哪里对了?

非常感谢,斯蒂芬.P

编辑:如果在事件发送周围的任何地方使用 Stop() 停止 MSMQ 处理程序,则会出现详细信息窗口然后立即消失......

EDIT2:在Slugart给出的解决方法之后,我设法完成了这项工作:

class EventListener
{
    Main control;

    public EventListener(Main main)
    {
         control = main;
    }

    public void ShowDetails(object sender, EventArgs e)
    {
        int numero = int.Parse(sender as string);
        control.Invoke((Action)(() => ShowDetails(numero)));
    }

    private void ShowDetails(int numero)
    {
        Details details = new Details(numero);
        details.Show();
    }
}

使用如下:

Core.TaskMessageQueueHandler tmqh = new Core.TaskMessageQueueHandler();
EventListener el = new EventListener(this);
tmqh.messageReceived += new System.EventHandler(el.ShowDetails);
4

1 回答 1

3

您正在Details主 GUI 线程之外的线程上创建和显示表单,而不是 STA 线程。

您的 EventListener 应该有一个正在运行的表单(可能是您的主表单)的引用,然后调用form.Invoke()它。

class EventListener
{
    Control control; // A valid running winforms control/form created on an STA thread.

    public void ShowDetails(object sender, string message)
    {
        int numero = int.Parse(message);
        control.Invoke(() => ShowDetails(numero))
    }

    private void ShowDetails(int numero)
    {
        Details details = new Details(numero);
        details.Show();
    }
}

同样作为发送者发送您的事件数据并没有真正遵循摆在您面前的事件模式。您想为此使用 EventArgs 参数,请使用 EventHandler 委托(在您的情况下为 EventHandler)。

于 2013-10-13T13:26:48.243 回答