c# - 在程序的另一个实例上显示表单
问题描述
我编写了一个程序,该程序使用 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();
}
}
解决方案
推荐阅读
- css - 在 Chrome 中查看时,小设备尺寸的媒体查询不起作用
- python - 从数据框创建子数据框
- c++ - 强制 lld 链接在不同 DWARF 版本中使用调试信息的可重定位文件
- angularjs - Angularjs 选择选项性能改进 - 按过滤器分组 3000 多个数据
- google-cloud-platform - 如何从另一个数据流中启动一个数据流
- javascript - 如何:在 node.js lambda 函数中等待/异步?
- python - 如何从操作系统环境变量创建字典?
- ios - libbson-1.0.0.dylib: mach-o, but not built for iOS 模拟器错误是在从 Github 添加 mongoSwift 驱动程序后尝试运行项目时显示
- progressive-web-apps - PWA 主屏幕“卸载”DOM 事件
- php - 使用 ReactPHP 定期向 Ratchet 中的特定客户端发送消息