首页 > 解决方案 > 在程序的另一个实例上显示表单

问题描述

我编写了一个程序,该程序使用 ApplicationContext 在其表单关闭时继续运行。通过单击托盘图标可以再次显示该表单,但我希望它在再次运行应用程序而不是运行该程序的另一个实例时也显示其表单。

我已经尝试实施将消息发送到 Windows 进程(不是其主窗口)问题中建议的解决方案,但我似乎无法让 PostMessage 工作。我已经成功地实现了命名管道,但是在获取等待消息与 ApplicationContext 通信的线程时遇到问题。

我知道我见过其他具有此功能的应用程序,所以我的问题是:这通常是如何完成的?我发现的所有解决方案似乎都适用于其他人,所以我一定遗漏了一些简单的东西。

编辑:

抱歉没有包括一个例子。我发现了问题,我在SynchronizationContext.Current设置之前就在使用它。我通过在构造表单而不是之前构造我的 MessageReceiver 类来修复它。这是我的代码,以防任何人发现它有用。

Program课堂上:

    private const byte Activate = 3 << 3;

    [STAThread]
    private static void Main()
        {
        using (var mtx =
            new Mutex(true, "{F6878DF0-C021-4B4F-934A-7FB03957E09F}",
                      out var createdNew))
            {
            if (createdNew)
                {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new AppContext(Activate));
                }
            else
                {
                //if the program is already running, make a NamedPipeServer
                //and wait for it to connect, then write the Activate message
                using (var pipeServer =
                    new NamedPipeServerStream("testpipe",
                                              PipeDirection.Out))
                    {
                    pipeServer.WaitForConnection();
                    pipeServer.WriteByte(Activate);
                    }
                }
            }
        }

在应用程序上下文中:

private TestForm _form;
private readonly MessageReceiver _receiver;

public AppContext(byte activateMessage)
        {
        _form = new TestForm();
        _receiver = new MessageReceiver(activateMessage);
        _receiver.MessageReceived += OnMessageReceived;
        //tell the receiver to begin its wait thread
        _receiver.BeginWait();
        //make sure the thread stops when the application closes
        ThreadExit += (sender, args) => _receiver.StopWait();
        _form.Show();
        }

private void OnMessageReceived(object sender, EventArgs args)
    {
    //recreate the form if it's been disposed
    if (_form.IsDisposed)
        _form = new TestForm();
    //bring it to the front if it's already open, or
    //show it if it's not open
    if (_form.Visible)
        _form.BringToFront();
    else
        _form.Show();
    }

MessageReceiver班级:

private class MessageReceiver
    {
        public event EventHandler MessageReceived;
        private readonly SynchronizationContext _sync;
        private Thread _waitThread;
        private readonly byte _activate;

        public MessageReceiver(byte activateMessage)
            {
            _sync = SynchronizationContext.Current;
            _activate = activateMessage;
            }

        public void StopWait()
            {
            _waitThread.Abort();
            }

        private void WaitInternal()
            {
            while (true)
                {
                using (var client = new NamedPipeClientStream(
                    ".", "testpipe", PipeDirection.In))
                    {
                    //block until we can connect to the pipe server
                    client.Connect();
                    //read a byte from the stream and check if it's
                    //the activate signal
                    if (client.ReadByte() != _activate) continue;
                    //if so, invoke the MessageRecieved event on the
                    //thread that created the MessageReceiver
                    _sync.Send(
                        state =>
                            MessageReceived?.Invoke(
                                this, EventArgs.Empty), null);
                    }
                }
            }

        public void BeginWait()
            {
            if (_waitThread.ThreadState == ThreadState.Running
             || _waitThread.ThreadState == ThreadState.AbortRequested)
                return;
            _waitThread = new Thread(WaitInternal);
            _waitThread.Start();
            }
    }

标签: c#multithreadingwinforms

解决方案


推荐阅读