Reputation: 3053
I have a UWP application that receives a dynamic updates via SignalR. I'm using Template10 and the SignalR listener is located in the ViewModel class.
When messages are received by SignalR - the Model is updated. The block of code that updates the model is wrapped in Despatcher method:
VM - method invoked by SignalR:
private async void AddOrder(WorkOrder order)
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
order.Lines = new ObservableCollection<WorkOrderLine>(order.Lines.OrderByDescending(m => m.QtyScanned < m.Qty);
this.Orders.Add(order);
});
}
Then inside of the model class I have this code (there is another child observablecollection on WorkOrderLine class):
private void TrolleyAllocations_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
RaisePropertyChanged("WorkOrderLineItems");
ForegroundColor = GetForegroundColour();
}
The GetForegroundColor is the following:
private SolidColorBrush GetForegroundColour()
{
try
{
if (WorkOrderLineItems.Where(m => m.Status == UnitStatus.Other).Any())
{
return new SolidColorBrush(Colors.Red);
}
else if (WorkOrderLineItems.Where(m => m.Status == UnitStatus.AssemblyLine).Any())
{
return new SolidColorBrush(Colors.Green);
}
else if (WorkOrderLineItems.Where(m => m.Status == UnitStatus.PreLoad).Any())
{
return new SolidColorBrush(Colors.Black);
}
else if (WorkOrderLineItems.Where(m => m.Status == UnitStatus.FullAndComplete).Any())
{
return new SolidColorBrush(Colors.LightGray);
}
return new SolidColorBrush(Colors.Black);
}
catch (Exception ex)
{
Debug.WriteLine($"Exception in foreground colour: {ex.Message} {ex.StackTrace}");
return null;
}
}
Now, on any new SolidColorBrush()
the wollowing exception is thrown:
The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))
Prior to the recent changes I was using the Conveter in x:Bind to do the work that GetForegroundColor method is doing (I have decided to change the approach due to the performance hit converters incur) - and it was working just fine. I'm also updating some of the other databound properties - which update UI (code omitted) and this works just fine.
Any ideas would eb greatly appreciated. It's been driving me insane.
Upvotes: 2
Views: 1518
Reputation: 707
You need to run your model's changes on the main thread. I've got the same problem in UWP using MVVM.
I think you need to wrap with a dispatcher your event's handler code in order to run it on the UI thread.
private void TrolleyAllocations_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
RaisePropertyChanged("WorkOrderLineItems");
ForegroundColor = GetForegroundColour();
}
}
Now your handler is called and fired from a background task, so GetForegroundColor()
is on the same thread.
Upvotes: 7