我正在使用Reactive UI爲Windows Phone 7.1開發我的第一個應用程序,而且我在使用ReactiveCollection類時遇到了困難。ReactiveCollection和無效的跨線程訪問
我的應用程序大致是關於訪問WP7 SQL CE引擎(LINQ to SQL)。我想使用ReactiveAsyncCommand在後臺執行數據操作。數據庫中的數據應該「自動地」出現在UI中,因此我決定使用ReactiveCollection作爲數據庫和UI之間的代理。
這裏是我的模型,所以你可以有一個更好的主意:
public class EncounteredModel
{
public ReactiveCollection<Fact> FactsCollection;
public ReactiveCollection<FactEntry> FactEntriesCollection;
private EncounteredModel()
{
using (EncounteredDataContext db = new EncounteredDataContext())
{
FactsCollection = new ReactiveCollection<Fact>(from fact in db.Facts select fact);
FactEntriesCollection = new ReactiveCollection<FactEntry>(from factEntry in db.FactEntries select factEntry);
}
FactsCollection.ItemsAdded.Subscribe(fact => { using (var db = new EncounteredDataContext()) { db.Facts.InsertOnSubmit(fact); db.SubmitChanges(); } });
FactsCollection.ItemsRemoved.Subscribe(fact => { using (var db = new EncounteredDataContext()) { db.Facts.DeleteOnSubmit(fact); db.SubmitChanges(); } });
FactEntriesCollection.ItemsAdded.Subscribe(factEntry => { using (var db = new EncounteredDataContext()) { db.FactEntries.InsertOnSubmit(factEntry); db.SubmitChanges(); } });
FactEntriesCollection.ItemsRemoved.Subscribe(factEntry => { using (var db = new EncounteredDataContext()) { db.FactEntries.DeleteOnSubmit(factEntry); db.SubmitChanges(); } });
}
private static EncounteredModel instance;
public static EncounteredModel Instance
{
get
{
if (instance == null)
instance = new EncounteredModel();
return instance;
}
}
}
在我的視圖模型我一直在使用2個不同的變種嘗試:
- 創建衍生反應的收集和綁定UI (使用ReactiveCollection.CreateDerivedCollection()方法,例如從EncounteredModel.FactsCollection派生而來,例如
- 使用
ObservableAsPropertyHelper<IEnumerable<Fact>>
,然後訂閱Model的ReactiveCollectionChanged
IObservable來填充OAPH。
不幸的是,兩種變體都會給我「無效的跨線程訪問」。堆棧跟蹤通常是這兩種方式的相同,這裏是一個變體1(縮短至顯著部分):
at MS.Internal.XcpImports.CheckThread()
at System.Windows.DependencyObject.GetValueInternal(DependencyProperty dp)
at System.Windows.FrameworkElement.GetValueInternal(DependencyProperty dp)
at System.Windows.DependencyObject.GetValue(DependencyProperty dp)
at System.Windows.Controls.ItemsControl.get_ItemsHost()
at System.Windows.Controls.ItemsControl.OnItemsChangedHandler(Object sender, ItemsChangedEventArgs args)
at System.Windows.Controls.ItemContainerGenerator.OnItemAdded(Object item, Int32 index, Boolean suppressEvent)
at System.Windows.Controls.ItemContainerGenerator.System.Windows.Controls.ICollectionChangedListener.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
at System.Windows.Controls.WeakCollectionChangedListener.SourceCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
at System.Windows.Controls.ItemCollection.NotifyCollectionChanged(NotifyCollectionChangedEventArgs e)
當我改變ReactiveCommand(不是異步之一),一切都很好。任何想法如何克服這一點?非常感謝提前。
嗨,感謝您的回答,它的工作原理(修改了一下我的需求,但我從你那裏得到了這個想法)。但是還有一個小問題:OAPH的故事是一樣的嗎?我的意思是,它是不是也將所有代碼都委託給UI線程? – Haspemulator
OAPH還保證它的事件將在UI線程上被觸發,是的 –