我正在设法从另一个线程中更新我的主UI (例如textblock)。到目前为止,我能够做到这一点的唯一方法是使用able对象。我遇到了一种情况,我不能使用and对象,最近有人告诉我使用MVVM / binding方法。我看了一些视频,做了一些例子,但我似乎无法让它发挥作用。
<TextBlock Name="txtblock1" Text="{Binding count}"></TextBlock>这是我的错误
异常引发:“System.Runtime.InteropServices.COMException”在System.Runtime.WindowsRuntime.dll异常中抛出:“System.Runtime.InteropServices.COMException”在mscorlib.ni.dll异常中抛出:“System.Runtime.InteropServices.COMException”在mscorlib.ni.dll中
视图(代码后面)
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
ViewModelexample obj = new ViewModelexample();
txtblock1.DataContext = obj;
obj.Methodasync();
}
}ViewModel
public class ViewModelexample : INotifyPropertyChanged
{
public string count { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected void onPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler !=null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public async void Methodasync()
{
await Method();
}
public Task Method()
{
return Task.Factory.StartNew(() =>
{
for (int i = 0; i < 100; i++)
{
Task.Delay(1000).Wait();
Debug.WriteLine(i.ToString());
count = i.ToString();
onPropertyChanged(i.ToString());
}
});
}
}对我可能做错了什么有什么想法吗?
谢谢
发布于 2016-03-31 05:21:51
您的count属性需要能够通知它已经更改。
public class ViewModelexample : INotifyPropertyChanged
{
private string _count;
public string count {
get { return _count; }
set {
if(value != _count) {
_count = value;
OnPropertyChanged(nameof(count));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
// the new Null-conditional Operators are thread-safe:
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private int _testCount = 0;
public void Method() {
testCount++;
Debug.WriteLine(testCount.ToString());
count = testCount.ToString();
}
}上述操作之所以有效,是因为新的空条件运算符是螺纹安全。
空条件成员访问的另一个用途是以线程安全的方式以更少的代码调用委托。..。这种新方法是线程安全的,因为编译器只生成一次计算PropertyChanged的代码,将结果保存在一个临时变量中。
要测试它,您可以编辑ViewModel方法,并让视图调用一个事件,比如加载页面或单击按钮。
public sealed partial class MainPage : Page
{
ViewModelexample obj = null;
public MainPage()
{
this.InitializeComponent();
obj = new ViewModelexample();
this.DataContext = obj;
}
public void OnSomeEventHandler() {
obj.Method();
}
}发布于 2016-03-31 10:47:30
我的假设是绑定将处理交叉线程调用。
不,这只适用于一些MVVM框架(如WPF)。因此,我更愿意把我所有的ViewModels都看作是UI的一部分。
使用代码示例,您应该能够使用Progress<T>
public async void Methodasync()
{
var progress = new Progress<int>(value =>
{
count = value;
onPropertyChanged("count");
});
await Method(progress);
}
public Task Method(IProgress<int> progress)
{
return Task.Run(() =>
{
for (int i = 0; i < 100; i++)
{
Task.Delay(1000).Wait();
Debug.WriteLine(i.ToString());
progress.Report(i);
}
});
}还请注意,我从StartNew更改为Run。一般情况下,不要将StartNew用于我在博客上描述的原因。
如果您“非常严肃”由于一些奇怪的原因不能使用Progress<T>,那么您可以直接使用反应性扩展或SynchronizationContext。
使用SynchronizationContext的示例
public Task Method()
{
var context = SynchronizationContext.Current;
return Task.Run(() =>
{
for (int i = 0; i < 100; i++)
{
Task.Delay(1000).Wait();
Debug.WriteLine(i.ToString());
var localI = i;
context.Post(() =>
{
count = localI;
onPropertyChanged("count");
});
}
});
}localI是给避免关闭循环变量的。
https://stackoverflow.com/questions/36324612
复制相似问题