我创建了WPF应用程序,然后通过删除app.xaml
并将构 build 置为类库将其转换为DLL。我正在使用C#Windows窗体来测试DLL。 WPF DLL已预加载,因此以后可以调用它以立即显示和显示,而不必等待加载。我要完成的工作是调用Show(ShowWPFApp)
并让代码等待,直到通过调用WPFAppResponse
翻转 bool 值为止(此操作是通过初始加载传递的)。我现在拥有的方式导致UI冻结。关于如何使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();
}
}
}
最佳答案
从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-part-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线程。
关于c# - 我如何使代码等到 bool 信号继续,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21414713/