2010-03-02 61 views
2

我正在通过仅仅制作一个WPF应用程序单实例的需求。 但是 - 我必须将命令行传递给第一个实例,然后执行一些UI操作。来自其他线程的WPF访问GUI

我正在使用Mutext检查已运行的实例,我使用NamedPipes将命令行转移到已经运行的实例。

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

UI操作是为TabControl添加一个新的Tab - 在新Tab的初始化过程中,一些工作已经完成 - 并且变量被初始化,甚至我想调用的方法在init中工作 - 但是当从调度程序失败。

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

谢谢!

回答

4

这很简单:

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

您可以从App.Startup从你的线程,从命名管道接收消息称此也。

这里的关键考虑因素是:

  1. 使用的BeginInvoke,而不是调用的,以防止调用线程从等待
  2. 使用DispatcherPriority.ApplicationIdle的保证应用程序完成初始化命令行处理之前
  3. 使用Application.Current.Dispatcher代替Window1.Dispatcher的情况下,窗口1尚未initialzed
+0

伟大的信息射线。我之前发布的解决方案是我遇到的问题,以解决我遇到的问题,并简单地转发该信息。我做了一些更多的研究,发现你发布了同样的东西(BeginInvoke可能会解决OP的问题)。我对使用lambda表达式而不是回调函数的更多信息感兴趣。我使用我在几个地方发布的代码,并且正在考虑改变它,如果有更好的方法。你有什么链接进入更深层次的解释?再次感谢! – Scott 2010-03-02 20:35:01

+1

@Scott:lambda表达式实际上只是语法糖。我在其他评论中提到的性能差异是什么让我们忽略了对Dispatcher.CheckAccess的调用。 Dispatcher.Invoke已经做了Dispatcher.CheckAccess()内部,因此调用Dispatcher.Invoke之前做重复工作和杂波的代码。当你在同一个线程性能相当于但是当你没有,的checkAccess()被调用三次,如果我们手动调用它(从调用代码的调用之前一次,一次,一旦在递归调用)。 – 2010-03-02 22:46:00

+0

再次感谢您的回复!这非常有趣!我发现的所有文章(包括msdn)都建议添加Dispatcher.CheckAccess以防止不必要的调用(请参阅链接)。我不打算怀疑,但我希望你能指点我一些文件。感谢您分享您的知识! 链接: http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.checkaccess(VS.100).aspx http://social.msdn.microsoft.com/论坛/ EN-US/WPF /线程/ 14f7ca5e-fb1c-433E-94d4-269c3ddcedec http://blog.decarufel.net/2009/03/good-practice-to-use-dispatcher-in-wpf.html – Scott 2010-03-02 23:41:02

2

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

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

事实上,您得到的“对象引用未设置为对象的实例”。错误消息意味着你还没有将对象实例化为新的。

+0

我会同意的这个评估。我也相信这里还有其他一些问题。我会尝试调试并找到您尝试访问的对象为null。 – Scott 2010-03-02 15:00:39

+0

看来我进入了某种竞争状态,正如我一步一步建立起来的那样,我非常想知道为什么这个该死的对象没有初始化。 我目前的工作解决方案是来自WinForms的糟糕的旧的DoEvents()。几个测试表明,它现在正在工作,根据需要,但如果任何人比DoEvents()更好的主意()我会很高兴,...... 谢谢! – JerryVienna 2010-03-02 15:35:13

+0

+1表示它不是WPF的调度员抱怨 – 2010-03-02 19:40:33