我正在使用下面的代码来显示WPF(MVVM)应用程序中的进度条状态,该应用程序基本上在线程上,但是,如果我使用的是调度程序线程,则其状态不会在UI上更新。
带螺纹:
Main()
{
Thread LoadApp = new Thread(MyData);
LoadApp.Start();
}
public void MyData()
{
ProgMessage = "10%";
ProgValue = 10;
var varAction = new List<Func<object>>();
varAction .Add(() => (MainViewMode1)ViewModel1.ViewModel1);
varAction .Add(() => (MainViewMode2)ViewModel2.ViewModel2);
varAction .Add(() => (MainViewMode3)ViewModel3.ViewModel3);
foreach (var action in varAction )
{
var obj = action();
ProgressMessage = // My message from VM
ProgressBarValue += // My message valuefrom VM;
}
}
这工作正常,但是因为现在我正在使用依赖项属性,所以遇到了交叉线程异常(STA),因此我将代码更改为:
Main()
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() =>
{
MyData();
}));
}
public void MyData()
{
ProgMessage = "10%";
ProgValue = 10;
var varAction = new List<Func<object>>();
varAction .Add(() => (MainViewMode1)ViewModel1.ViewModel1);
varAction .Add(() => (MainViewMode2)ViewModel2.ViewModel2);
varAction .Add(() => (MainViewMode3)ViewModel3.ViewModel3);
foreach (var action in varAction )
{
var obj = action();
ProgressMessage = // My message from VM
ProgressBarValue += // My message valuefrom VM;
}
}
现在,我摆脱了线程错误,但是它不更新UI上的进度栏状态吗?
有什么线索吗?
在您放弃对调度程序线程的控制之前,UI元素不会更新。通常,您可以通过返回事件循环来做到这一点,这通常意味着只返回即可。但是,如果您有很多工作要做循环,那么这实际上是不实际的。因此,通常,您不想在UI线程上进行此类工作。
当您说“使用依赖项属性”时,是否表示ViewModel类的属性是依赖项属性?您可能需要重新考虑,因为它阻止了多线程的使用。如果将它们设置为普通的非自动属性,则仍可以使用数据绑定将它们连接到UI。要使UI在属性更改时更新,您需要实现INotifyPropertyChanged
,并使属性引发更改通知,然后您将发现可以像第一个示例一样在工作线程上进行工作,并且如果将这些属性绑定到UI,您将不会获得线程异常,并且可以正常更新。
(WPF的数据绑定系统检测UI线程以外的线程上的绑定属性何时发生更改,并自动安排从正确的线程更新UI。但是,如果您想利用此优势,则不能在VM中使用DP。 ,因为DPS具有线程相似性。)
DoEvents
其他人提出的样式方法确实可以奏效,但这是有问题的,我避免了。它启用了重新进入功能-如果用户与您的应用进行交互而导致事件处理程序运行,则它们将在对的调用中运行Dispatcher.PushFrame
。这不一定是问题,但是很容易陷入混乱。
还有一种方法是在工作线程上完成工作,但是要使用Dispatcher.Invoke
来调用更新ProgressMessage
和ProgressBarValue
属性的方法。这样,您的工作就在工作线程上进行(使UI线程可以自由更新),但是您将在UI线程上更新这些DP,从而避免了该错误。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句