2013-10-13 83 views
0

我创建了两个单独的Windows窗体在C#中使用MSMQ进行通信的应用程序。以下是它的工作方式,但看起来很简单:处理事件接收MSMQ消息(线程问题?)之后

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

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

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

下面是我使用的应用2部分代码:

/*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(); 
    } 
} 

我有什么错?我去哪里了?

非常感谢, Stephane.P

编辑:如果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

你创建和在除主界面线程,而不是在这一个STA线程的线程上显示的形式Details

你的事件监听应该有跑步方式的引用(主窗体也许),然后调用它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在你的情况下)。

+0

非常感谢,那帮助我了解我的错误!然而,当我尝试你的代码,我发现周围的'control.Invoke这个错误(()=> ShowDetails(NUMERO))'行:“无法转换lambda表达式键入‘System.Delegate’,因为它不是一个委托类型”。那是什么意思?编辑:没关系,我GOOGLE了它,它应该作为一个行动铸造。 –