WPF从其他线程访问GUI

发布于 2024-08-23 07:16:13 字数 408 浏览 7 评论 0原文

我正在满足仅创建 WPF 应用程序单个实例的要求。 但是 - 我必须将命令行传递到第一个实例,然后执行一些 UI 操作。

我使用 Mutext 来检查已经运行的实例,我使用 NamedPipes 将命令行传输到已经运行的实例。

但当然我不在正确的线程中访问“Window1”。 我尝试在静态类中存储对“Window1”的引用,然后使用调度程序调用“Window1”中的方法,但是,一旦我尝试访问变量(“Window1”中的类范围),我就会收到“未将对象引用设置为对象的实例。”

UI操作是向TabControl添加一个新选项卡 - 在新选项卡的初始化期间完成了一些工作 - 并且变量被初始化,甚至我想调用的方法在初始化期间工作 - 但是当从调度程序调用时它失败。

任何提示,如何做到这一点?我在这里走错路了吗?

谢谢!

I am working through the requirement to make a WPF Application single instance only.
However - I have to pass the command line to the first instance and then perform some UI action.

I am using a Mutext to check for already running instances, I do use NamedPipes to transfer the command line to the already running instance.

But of course I am not in the correct Thread to access "Window1".
I tried to store a reference to "Window1" in a static class and then use the Dispatcher to call a Method in "Window1", however, as soon as I try to access a variable (class wide scope in "Window1") I receive a "Object reference not set to an instance of an object."

The UI Action is to add a new Tab to a TabControl - during initialization of the new Tab some work is done - and the variables are initialized and even the method I want to call works during the init - but when called from the Dispatcher it fails.

Any hints, how to do this? Am I on the wrong track here?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

北音执念 2024-08-30 07:16:13

这很简单:

void ProcessCommandLine(string commandLine)
{
  Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
  {
    ... code to process the command line here ...
  });
}

您可以从 App.Startup 以及从命名管道接收消息的线程中调用它。

这里的关键考虑因素是:

  1. 使用 BeginInvoke 而不是 Invoke 来防止调用线程等待
  2. 使用 DispatcherPriority.ApplicationIdle 来保证应用程序在处理命令行之前完成初始化
  3. 使用 Application.Current.Dispatcher 而不是 Window1.Dispatcher case Window1 尚未初始化

This is easy:

void ProcessCommandLine(string commandLine)
{
  Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
  {
    ... code to process the command line here ...
  });
}

You can call this from your App.Startup and also from your thread that receives messages from the named pipe.

The key considerations here are:

  1. Use of BeginInvoke instead of Invoke to prevent the calling thread from waiting
  2. Use of DispatcherPriority.ApplicationIdle to guarantee the application has finished initializing before the command line is processed
  3. Use of Application.Current.Dispatcher instead of Window1.Dispatcher in case Window1 has not yet been initialzed
不必了 2024-08-30 07:16:13

这是不对的,您确定互斥体将控制正确传递给当前正在运行的应用程序实例吗?

如果是线程 UI 访问问题,您应该收到此错误:调用线程无法访问此对象,因为不同的线程拥有它。

事实上,您收到“对象引用未设置到对象实例”。错误消息意味着您尚未将该对象实例化为新对象。

That's not right, are you certain that the mutex is passing control correctly to your currently running instance of the application?

If it was a thread UI access issue, you should have received this error: The calling thread cannot access this object because a different thread owns it.

The fact that you're getting an "Object reference not set to an instance of an object." error message means that you've not yet instantiated the object as new.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文