【发布时间】:2013-06-08 14:00:39
【问题描述】:
我在从 db 获取数据并在 UI 中异步显示时遇到问题。 我正在使用 MVVM 灯,当我单击按钮时,会在 ViewModel 中触发操作:
private void SearchQuery(string query)
{
_redisModel.GetFriendsListAsync(query);
}
在某些时候 GetFriendsListCompleted 被后台线程调用,通知 viewmodel 工作已完成。 此时我需要更新 ListBox ItemSource。但是当我尝试更新时,我得到了 “调用线程无法访问此对象,因为不同的线程拥有它” 我试过 Dispatcher.CurrentDispatcher.Invoke(),App.Current.Dispatcher.Invoke() 和其他魔法,但它仍然不起作用。
我尝试将 UI 调度程序提供给 ViewModel,然后从那里调用它 - 没有用。
private string filterText = string.Empty;
public string FilterText
{
get { return filterText; }
set
{
filterText = value;
this.RaisePropertyChanged(() => this.FilterText);
this.FriendsList.View.Refresh(); // Here where exception is happening.
}
}
我试图将这一行改为
Dispatcher.Invoke(DispatcherPriority.Normal, new Action( () =>this.FriendsList.View.Refresh())); - 还是一样。
我正在使用 Telerik ListBox 来显示项目。 FriendList 是 CollectionViewSource(http://www.telerik.com/help/wpf/radlistbox-overview.html)。当我使用 WPF 控件示例中的 Telerik 示例时,它可以工作。当我使用我的异步方法时,问题开始出现。 视图类型为 System.ComponentModel.ICollectionView,用于过滤和分组。
我也尝试将 ObservableCollection 分配给 ListBox 的 Items 属性,但它也不起作用。
关于 _redisModel.GetFriendsListAsync 如何工作的更多细节: 最后(在所有调用链之后)它在这里结束:
public GetAsyncResult(Func<T> workToBeDone, Action<IAsyncResult> cbMethod, Object state)
{
_cbMethod = cbMethod;
_state = state;
QueueWorkOnThreadPool(workToBeDone);
}
ThreadPool.QueueUserWorkItem(state =>
{
try
{
_result = workToBeDone();
}
catch (Exception ex)
{
_exception = ex;
}
finally
{
UpdateStatusToComplete(); //1 and 2
NotifyCallbackWhenAvailable(); //3 callback invocation
}
});
在视图模型中我有方法:
private void GetFriendsListCompleted(object sender, ResultsArgs<Friend> e)
{
if (!e.HasError)
{
var curr = e.Results;
if (curr != null)
{
this.FriendsList= new CollectionViewSource();
this.FriendsList.Source = list;
this.FriendsList.Filter += this.FriendFilter;
FilterText = "";
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(
() => this.FriendsList.View.Refresh()));
}
}
有人可以帮我解决这个问题吗? 谢谢
【问题讨论】:
-
编辑您的问题并为您的问题添加一些上下文。
FriendsList的类型是什么。您从 VM 访问的View属性是什么?
标签: wpf multithreading mvvm-light