我有一个现有的 WPF 应用程序,它有几个部分。每个部分都是一个 UserControl,它实现了一个接口(interface)。
接口(interface)指定了两个方法:void LoadData([...])
和 bool UnloadData()
。
这些方法是由 UI 线程调用的,所以如果它很耗时,我们需要在 backgroundworker 中完成我们的工作。
LoadData
没有问题,因为我们可以异步更新 UI。问题在于 UnloadData()。
如果我们真的可以离开当前 View ,这应该返回。
这是根据数据的当前状态(已保存/已修改/无效)计算得出的:
- 保存返回真,
- Invalid 询问你是否想留下来节省一些 更正数据或不保存离开
- 修改告诉你可以 要么取消你的改变(返回真),要么继续 编辑(返回 false),或者保存当前数据(返回 true)
问题出在“修改 -> 保存”。这是一种耗时的方法,因此为了尊重应用程序的理念,我们应该在后台线程中运行它(带有繁忙指示器)。
但如果我们只是启动线程并转到下一个部分,它会返回“true”给方法调用,我们将直接启动下一个 View 。
就我而言,在保存本地数据之前加载下一个 View 可能是个问题。
所以:
有没有办法在不阻塞 UI 的情况下等待后台线程完成后再返回“true”?
public bool UnloadData(){
if(...){
LaunchMyTimeConsumingMethodWithBackgroundWorker();
return true;//Only when my time consuming method ends
}
//[...]
}
重要编辑 也许我不够清楚:我知道如何使用 BackgroundWorker 或 TPL。我的问题是父类(调用 UnloadData() 的那个)是一个我无法编辑的类(出于多种原因:它在另一个不会重新加载的 DLL 中,它已经与 70 多个用户控件一起使用,所有这些都是单独的projects(dll),通过反射加载。
这不是我的选择,我觉得这不好,但我现在必须处理它。我主要是在寻找让我的方法等待我的方法返回的方法。我不确定这是否可能。但我正在寻找解决方法,它将节省我数周的工作时间。
最佳答案
好吧,现在我很兴奋,因为我想我可能自己发现了一些东西......
因此,您要做的是:创建一个 DispatcherFrame,将该框架推送到 Dispatcher,然后在 RunWorkerCompleted 中将框架的 Continue 设置为 false。
这是目前的代码:
public void Function()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += TimeConsumingFunction;
var frame = new DispatcherFrame();
worker.RunWorkerCompleted += (sender, args) =>
{
frame.Continue = false;
};
worker.RunWorkerAsync();
Dispatcher.PushFrame(frame);
}
private void TimeConsumingFunction(object sender, DoWorkEventArgs doWorkEventArgs)
{
Console.WriteLine("Entering");
for (int i = 0; i < 3; i++)
{
Thread.Sleep(1000);
}
Console.WriteLine("Exiting");
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
Function();
Console.WriteLine("Returns");
}
关于c# - WPF/C# 不要阻塞 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13934697/