簡體   English   中英

如何使代碼等待直到bool發出信號才能繼續

[英]How do i make the code wait until a bool signals it to continue

我創建了一個WPF應用程序,然后通過刪除app.xaml並將構建設置為類庫將其轉換為DLL。 我正在使用C#Windows窗體來測試DLL。 WPF DLL已預先加載,因此可以稍后調用它以立即顯示和顯示,而無需等待加載。 我想要完成的是調用Show(ShowWPFApp)並使代碼等待,直到通過調用WPFAppResponse來翻轉布爾值(此操作通過初始加載傳入)。 我現在擁有它的方式導致UI凍結。 如何在沒有UI凍結的情況下讓它等待的任何想法?

Windows窗體調用WPF DLL

namespace WindowsFormsDLLTest
{
    public partial class Form1 : Form
    {
        WPFDLL.LoadWPFApp wpfApp = null;
        public Form1()
        {
            InitializeComponent();
        }

        private void btnLoadWPFApp_Click(object sender, EventArgs e)
        {
            wpfApp = new WPFDLL.LoadWPFApp();
            try
            {
                wpfApp.Load();
            }
            catch (Exception ex)
            {

            }
        }

        private void btnShowWPFApp_Click(object sender, EventArgs e)
        {
            try
            {
                string result = null;
                result = wpfApp.ShowWPFApp("John Doe");
            }
            catch (Exception ex)
            {

            }
        }
    }
}

WPF DLL應用程序

namespace WPFDLL
{
    public class LoadWPFApp
    {
        private Application application = null;
        private MainWindow mainWindow = null;
        private bool waitOnShowWindow {get; set;}
        private string returnResults = null;

        public void Load()
        {
            StartLoadingWPFApp();
        }

        [STAThread]
        private void StartLoadingWPFApp()
        {
            application = new Application();

            SplashScreenWindow splashWindow = new SplashScreenWindow();
            splashWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            splashWindow.Show();

            try
            {
                mainWindow = new MainWindow(WPFAppResponse);
                mainWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                splashWindow.Close();

                application.Run();
            }
            catch (Exception ex)
            {
                splashWindow.Close();
                MessageBox.Show("Error starting application:" + Environment.NewLine + ex.ToString(), "WPF App Error", MessageBoxButton.OK, MessageBoxImage.Error);
                mainWindow = null;
            }
        }

        public string ShowWPFApp(string person)
        {
            returnResults = null;
            mainWindow.LoadPerson(person);
            mainWindow.Show();

            while(waitOnShowWindow)
            {
                //Code waits until bool is set to false
            }

            return returnResults;
        }

        public void WPFAppResponse(string person)
        {
            returnResults = person;
            waitOnShowWindow = false;
            mainWindow.Hide();
        }
    }
}

可以使用解決方法

await Task.Delay(1000);

在你的while循環中。 這可能會延遲while循環的每次運行,並且UI不會凍結。 我不確定這是否適用於您的情況。 試試讓我知道。 希望這可以幫助。

您需要將執行返回給UI線程的事件循環,以便UI不會凍結。 在表單應用程序中,您可以執行以下操作:

while(waitOnShowWindow)
{
    //Code waits until bool is set to false
    System.Windows.Forms.Application.DoEvents();
}

編輯:

正如Eric指出的那樣,使用DoEvents()時可能存在問題,所以不要隨意使用它。 請參閱如何使用DoEvents()而不是“邪惡”?

在像這樣的測試應用程序中,它允許代碼工作。 但是,更好的解決方案是重新構造應用程序,以便在不需要調用時使用多線程(如果需要)。

從Windows窗體啟動WPF應用程序很麻煩。 你偶然發現了一個相當復雜的線程問題。 一般建議是將WPF應用程序創建為WPF控件庫。 但是,我發現這可能無法解決您所擁有的緩慢加載問題,這就是您制作輕量級WinForms包裝應用程序的原因。

問題是你的循環:

while(waitOnShowWindow)
{
    //Code waits until bool is set to false
}

該循環在UI線程上運行,阻止它處理Windows消息。 (如果這個概念對你來說是新的,那么請查閱它,因為它對於Windows UI的東西很重要。)為了響應UI,它必須運行Windows消息循環。 我看到兩個解決方案:

  1. 創建自己的消息循環。
  2. 立即返回,然后稍后得到結果。

解決方案1:要創建自己的消息循環,您需要使用Dispatcher.Run()或Dispatcher.PushFrame()之類的東西。 試試這個,看它是否有效:

public string ShowWPFApp(string person)
{
    returnResults = null;
    mainWindow.LoadPerson(person);
    mainWindow.Show();
    Dispatcher.CurrentDispatcher.Run();
    // do whatever to get the results
    return returnResults;
}

如果這不起作用,您可能需要使用PushFrame()。 如果Dispatcher.Run()不起作用,這里有一些關於該主題的更深入的文章。 http://www.codeproject.com/Articles/152137/DispatcherFrame-Look-in-Depth http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread -第1部分/

解決方案2:

public void ShowWPFApp(string person)
{
    returnResults = null;
    mainWindow.LoadPerson(person);
    mainWindow.Show();
}

現在,調用將不會阻止UI線程,並且將出現WPF窗口。 Windows窗體應用程序正在運行消息循環,因此WPF現在可以運行。 但是你怎么得到結果!? 由於它現在以異步方式運行,因此您必須找到一些其他方法來獲取返回值。 我認為MainWindow類上的事件是最簡單的方法。

另外:[STAThread]屬性沒有做任何事情。 [STAThread]僅對應用程序的入口點有意義。 幸運的是,您的Windows窗體應用程序已經將[STAThread]放在Main()方法上,因此您的線程是一個STA線程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM