0

C# で、通信に MSMQ を使用する 2 つの個別の Windows フォーム アプリケーションを作成しました。これがどのように機能するかですが、それは十分に単純に見えました:

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

どこで私は間違えましたか?私はどこに行ったのですか?

どうもありがとう、Stephane.P

編集: MSMQ ハンドラーがイベント送信の前後のどこかで Stop() で停止されると、詳細ウィンドウが表示され、すぐに消えます...

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

DetailsSTA スレッドではなく、メイン GUI スレッド以外のスレッドでフォームを作成および表示しています。

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 に答える