代码仅在调用Application.Run()WPF应用程序时启动

时间:2014-01-13 15:55:16

标签: c# wpf multithreading

我有一个在class A中调用的方法,它在class B中定义:

class B{
      [STAThread]
        public static void ScanForAxisCameras() {
                DNSSDService service = new DNSSDService();
                DNSSDEventManager eventManager = new DNSSDEventManager();
                eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(eventManager_ServiceFound);
                DNSSDService browse = service.Browse(0, 0, "_axis-video._tcp", null, eventManager);
                Application.Run();//if not invoked everything above does not start
            }
}

class A{ ...before invoking..... B.ScanForAxisCameras(); ....after invoking....}

class B中的代码“启动”/仅在我调用Application.Run()时有效。 但它会导致class A ....after invoking....方法中的所有代码无法正常工作。如何处理它以免冻结应用程序?

修改class Aclass MainWindow.xaml.cs。它是WPF应用程序。

public partial class MainWindow : Window {

        public MainWindow() {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e) {
            createGUI();
        }

        private void createGUI() {

            LocalNetworkScanner.ScanForAxisCameras();//when there is no Application.Run()  ScanForAxisCameras() does not work.
}
}

5 个答案:

答案 0 :(得分:1)

Application.Run启动该特定线程的消息循环,如果没有消息循环,则没有通知您的对象知道他们必须做某事。

  

B类中的代码“启动”/只有在我调用Application.Run()时才有效。 但它导致在调用....方法后,A类中的所有代码都无法正常工作

Run是一个阻塞调用,因此在应用程序关闭之前,即在您退出消息循环时,无法访问该调用之后的任何代码。

  

如何处理它以便它不会冻结应用程序?

总之,你不能。 Run将始终阻止,因此您需要在应用程序启动时运行的任何代码都必须在调用之前发生。


在您编辑后提到这是一个WPF应用程序,然后Application.Run作为static方法不是正确的方法。如果您需要在应用程序启动时运行初始化,那么您可以执行已建议的操作并覆盖Run类的Application方法,或者(可能更恰当地)您可以挂钩{ {3}}事件,例如

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        // code before startup
        base.OnStartup(e);
        // code after startup
    }
}

答案 1 :(得分:1)

您可以在Run()文件的App中引入新的App.xaml.cs方法。 在可以在应用程序本身初始化之前执行自定义操作。 更多信息here

public partial class App : Application
{
    public new void Run()
    {
        // Do your stuff here
        B.DoStuff();

        // Call the base method
        base.Run();
    }
}

答案 2 :(得分:1)

您调用ScanForAxisCameras()的WPF UI线程已经有一个消息循环。我相信您的代码存在的问题是您在ScanForAxisCameras 中创建的所有对象具有本地范围

public static void ScanForAxisCameras() {
        DNSSDService service = new DNSSDService();
        DNSSDEventManager eventManager = new DNSSDEventManager();
        eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(eventManager_ServiceFound);
        DNSSDService browse = service.Browse(0, 0, "_axis-video._tcp", null, eventManager);
        Application.Run();//if not invoked everything above does not start
}

如果没有Application.Run(),您的对象(serviceeventManagerbrowse)可能会在ScanForAxisCameras完成后被销毁并最终确定。因此,您正在寻找的事件(如ServiceFound)可能甚至没有机会被解雇。

如果您致电Application.Run(),则ScanForAxisCameras不会退出(至少在Application.Run()退出之前不会退出)。这可以使你的物体保持活力和功能。

尝试重构代码,以便在类的成员字段(或静态变量,FWIW)中保留对这些对象的引用。我认为应该解决这个问题。

[EDITED] 在旁注中,[STAThread]属性在该上下文中没有意义(除非您使用ScanForAxisCameras作为新线程的入口点 - 显然,这不是这种情况。)

答案 3 :(得分:0)

在这种情况下,您似乎需要在另一个类中添加Application.Run()。 Run()不接受任何内容,ApplicationContext,Form。这将控制应用程序的生命周期,并应在A类之前调用​​,除非A类是入口点。

有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/ms157900.aspx

答案 4 :(得分:0)

调用Main方法时, Windows窗体应用程序启动。您可以在Main函数上实现初始化过程。但是,要完全初始化 Windows窗体应用程序并开始路由 Windows窗体事件,您需要调用Application.Run。

您可以阅读有关申请here

的信息