2012-01-23 58 views
2

我正在使用其他人編寫的獲取市場數據的服務。它連接到他們的服務器,併發送一個符號併發回數據。那麼我試圖用它來打開多個視圖,以便您可以獲取多個符號的市場數據。這樣做的方式是我的ViewModel訂閱單例事件IncomingMessage,並且如果消息包含ViewModel的符號,它將它放入ObservableCollection中。這就是問題所在。C#單例UI線程問題

如何將事件消息安全地添加到我的收藏夾中?

[編輯] 我相信異常被拋出,因爲我的ObservableCollection綁定到我的視圖上的DataGrid。

+1

你指的是什麼技術中的視圖和視圖模型? ASP.NET MVC? – StriplingWarrior

+0

鎖定關鍵字不會有幫助嗎? http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx – rskar

+0

帶有WPF的MVVM。我認爲這是因爲將ObservableCollection綁定到我的視圖 – Stephen

回答

3

您需要將對Add方法的調用封送到UI線程。在棱鏡這通常是與該事件聚合完成,但如果你不使用棱鏡:

假設你有某種類型的Tick代表您的市場數據,以及這些數據的事件只是一個System.Action<Tick>

dataSource.IncomingMessage += (tick) => Application.Current.Dispatcher.Invoke(new Action<Tick>(AddTheTick), tick); 

,或者簡單

dataSource.IncomingMessage += (tick) => Application.Current.Dispatcher.Invoke(new Action<Tick>(myObservableCollection.Add), tick); 
+0

我收到錯誤「非靜態字段,方法或屬性需要對象引用'System.Windows.Threading.Dispatcher.Invoke(System.Delegate,params object [])'」我正在使用您的頂部的例子,因爲我需要對數據進行一些驗證。 – Stephen

+0

使用'Application.Current.Dispatcher' - 我將相應地編輯 –

+0

謝謝,這是完美的工作。 – Stephen

3

ObservableCollection<T>通常不能從後臺線程更新。您需要使用Dispatcher.Invoke()Dispatcher.BeginInvoke()以確保數據添加到集合所屬的線程中。

Application.Current.Dispatcher.Invoke((Action)(() => myObservableCollection.Add(value))); 

這是一個相當常見的任務,這是值得創建一個擴展方法來照顧這對你:

static class ObservableCollectionExtensions 
{ 
    internal static void InvokeAdd<T>(this ObservableCollection<T> self, T item) 
    { 
     Application.Current.Dispatcher.Invoke((Action<T>)self.Add, item); 
    } 

    internal static void BeginInvokeAdd<T>(this ObservableCollection<T> self, T item) 
    { 
     Application.Current.Dispatcher.BeginInvoke(new Action<T>(self.Add), item); 
    } 
} 

這樣你可以安全的幾個按鍵,然後輸入這個:

myObservableCollection.InvokeAdd(value); 
+0

謝謝,我會這樣做的。 – Stephen