[英]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.