使用外部C#项目关闭WPF项目时出现问题

fumotvh3  于 2023-05-30  发布在  C#
关注(0)|答案(1)|浏览(182)

一点背景:我有一个外部应用程序(TestStand),它调用WPF(MVVM)应用程序并与之通信。这些交互是通过另一个项目进行的,这使得我可以很容易地示例化视图和视图模型,这要归功于这个接口项目的静态属性和方法。
你会发现一个简单的架构图的图片。
https://i.stack.imgur.com/IziKu.png
我的问题如下:
我通过STA单元设置的线程例程启动视图(以便能够访问mainWindow构造函数)。由于视图的datacontext链接到了viewModel的一个示例,所以我能够访问这个viewModel的属性和方法(之后绑定魔法在视图和viewmodel之间完成工作)。当我试图关闭视图时出现问题。事实上,当第一个线程打开视图时,它就成为了视图的所有者(视图由线程处理),而我自己无法做到这一点。
下面是用于启动视图的线程:

public static void IHMSiteGisement(SequenceContext context, string nameAssemblyParameters, out bool errorOccured, out int errorCode, out string errorMessage)
{
    errorOccured = false;
    errorCode = 0;
    errorMessage = string.Empty;
    viewModel = null;

    newWindowThread = new Thread(new ThreadStart(OpenWindow))
    {
        Name = "WindowManager",
        IsBackground = true
    };
    newWindowThread.SetApartmentState(ApartmentState.STA);
    newWindowThread.Start();
}

下面是委托'ThreadStart'调用的OpenWindow方法:

private static void OpenWindow()
{
    AppWPF = new MainWindow();
    viewModel = new MainWindowViewModel();
    AppWPF.DataContext = viewModel;
    AppWPF.Show();

    Dispatcher.Run();
}

首先,我简单地尝试使用view.Close()关闭视图。不起作用的剧透警告--> Visual Studio告诉我,我无法访问此方法,因为视图由特定线程管理,而我当前使用的线程与此不同。
然后我尝试使用第一个线程来执行view.Close()命令。所以我修改了我的'OpenWindow'方法,如下所示:

private static void OpenWindow()
{
    AppWPF = new MainWindow();
    viewModel = new MainWindowViewModel();
    AppWPF.DataContext = viewModel;
    AppWPF.Show();

    //Dispatcher.Run();

    while (!IsAskedtoClose);
        AppWPF.Close();
}

我注解了代码行(Dispatcher.Run(),因为如果没有注解,代码就不会到达while循环。如果您忘记提到while循环冻结了我的GUI,那么测试是成功的。
接下来,我尝试使用我的第一个线程和另一个委托方法,但我得到了与第一次尝试相同的错误。
我还尝试使用Application.Current.Shutdown();,但当应用程序由TestStand启动时,Application.Current()返回空值(而不是当我由应用程序控制台启动时)。
我很确定我得到的错误是由于我对线程机制的误解,我在这里发帖所寻找的是为了解决我的问题,但也要有或能够找到知识来理解线程及其机制。

sg2wtvxw

sg2wtvxw1#

以下是我实施的解决方案
首先打开应用程序:

public static void OpenHMI(SequenceContext context, out bool errorOccured, out 
int errorCode, out string errorMessage)
    {
        errorOccured = false;
        errorCode = (int)EErrorCode.NoError;
        errorMessage = string.Empty;

        try
        {
            _newWindowThread = new Thread(new ThreadStart(WindowThreadRoutine));
            _newWindowThread.SetApartmentState(ApartmentState.STA);
            _newWindowThread.Name = "WindowManager";
            _newWindowThread.IsBackground = true;
            _newWindowThread.Start();
        }
        catch (Exception ex)
        {
            errorOccured = false;
            errorCode = (int)EErrorCode.ErrorWhenTryingToOpenHMI;
            errorMessage = string.Empty;
        }
    }

下面是通过open方法启动的线程例程:

private static void WindowManagerThreadRoutine()
    {
        try
        {
            _appWPF = new MainWindow();
            _viewModel = new MainWindowViewModel();

            _appWPF.DataContext = _viewModel;
            _appWPF.CloseAppAsked += (sender, args) => { OnCloseCommand(); };
            _appWPF.Show();

            Dispatcher.Run();
        }
        catch (Exception ex)
        {
            throw;
        }
    }

然后,这是我如何关闭我的应用程序:

public static void CloseHMI(SequenceContext context, out bool errorOccured, out int errorCode, out string errorMessage)
    {
        errorOccured = false;
        errorCode = (int)EErrorCode.NoError;
        errorMessage = string.Empty;

        try
        {
            if (!(_appWPF == null))
            {
                _appWPF.Dispatcher.BeginInvoke((Action)_appWPF.Close);
            }

            if (!(_newWindowThread == null))
            {
                Dispatcher.FromThread(_newWindowThread).InvokeShutdown();
            }

            if (_newWindowThread.IsAlive)
            {
                _newWindowThread = null;
                _appWPF = null;
            }
        }
        catch (Exception ex)
        {
            errorOccured = false;
            errorCode = (int)EErrorCode.ErrorWhenTryingToCloseHMI;
            errorMessage = string.Empty;
        }
    }

希望这会有所帮助,感谢您的评论和支持。我愿意接受任何改进我答案的建议。

相关问题