我正在创建一个wpf应用程序,它在后面执行许多任务,但仍然需要UI响应并显示各种后台任务的状态。它还可以选择不显示UI,在这种情况下,应该丢弃状态消息而不创建主表单的实例。
我试图删除
StartupUri="MainWindow.xaml"
。然后,在App.xaml.cs中,我有
`
public App()
{
Startup += new StartupEventHandler(App_Startup);
}
void App_Startup(object sender, StartupEventArgs e)
{
// Code which loads application settings is here
if (pf.ShowUI)
{
MainWindow mainWindow = new MainWindow();
mainWindow.Show();
}
// The background processes will begin here.
}`
如果需要,这会显示主窗体并启动所有后台进程。这部分有效。
为了将消息从后台发送到用户界面,我实现了一个非常基本的信使:
`
internal interface IMessageHandler
{
void ReceiveMessage(string message);
}
internal class Messenger
{
private static List<IMessageHandler> _handlers;
internal static void AddHandler(IMessageHandler handler)
{
_handlers.Add(handler);
}
internal static void RemoveHandler(IMessageHandler handler)
{
try
{
_handlers.Remove(handler);
}
catch (Exception ex) {}
}
internal static void Broadcast (string message)
{
foreach (IMessageHandler handler in _handlers)
{
handler.ReceiveMessage(message);
}
}
}`
主窗体实现了IMessageHandler接口,并在启动时将自身添加到Messenger作为处理程序。需要向主表单发送状态的任何进程只需要调用信使的Broadcast
方法。
我遇到的问题是,在后台进程完成之前,消息不会显示在表单上,并且UI也会被锁定。
处理接收消息的UI中的代码如下:
`
public void ReceiveMessage(string message)
{
Dispatcher.Invoke(DispatcherPriority.Normal,
new Action<string>(AddText),
message);
}
private void AddText(string text)
{
Label myLabel = new Label();
myLabel.Content = text;
stackPanel1.Children.Add(myLabel);
if (stackPanel1.Children.Count > 5)
{
stackPanel1.Children.RemoveAt(0);
}
}`
为什么我的后台进程会冻结我的UI?我该怎么做才能防止它?为什么我的UI没有使用状态消息进行更新?
答案 0 :(得分:1)
我遇到了同样的问题,this blog post帮助我解决了问题。
答案 1 :(得分:0)
也许这是你的问题:
Dispatcher.Invoke(DispatcherPriority.Normal,
new Action<string>(AddText),
message);
尝试将此更改为,
Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action<string>(AddText),
message);
因为当您使用Invoke
时,该方法会被执行并且应用程序等待它完成,但是使用BeginInvoke
方法将被异步调用,并且应用程序继续执行{{1}中引用的方法{1}}已执行。
答案 2 :(得分:0)
使用以下代码以避免冻结UI。在我的应用程序中,我使用了BackgroundWorker类。通过使用代码更改表单上的任何内容,将引发运行时错误。
我使用下面的代码来避免这种情况,它对我来说非常适合。
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
{
rtf_status.AppendText("Validating XML against schema...Please wait\n");
}));
请注意括号之间的部分('{}')如果您希望更改表单上的内容,则应放置代码。