[英]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:要創建自己的消息循環,您需要使用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.