【问题标题】:UWP SolidColorBrush - The application called an interface that was marshalled for a different thread exceptionUWP SolidColorBrush - 应用程序调用了为不同线程异常编组的接口
【发布时间】:2017-12-18 19:41:56
【问题描述】:

我有一个通过 SignalR 接收动态更新的 UWP 应用程序。我使用的是 Template10,SignalR 监听器位于 ViewModel 类中。

当 SignalR 收到消息时 - 模型会更新。更新模型的代码块包装在 Despatcher 方法中:

VM - 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);
        });
    }

然后在模型类内部我有这段代码(WorkOrderLine 类上还有另一个子 observablecollection):

private void TrolleyAllocations_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            RaisePropertyChanged("WorkOrderLineItems");
            ForegroundColor = GetForegroundColour();
        }

GetForegroundColor 如下:

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;
        }
    }

现在,在任何new SolidColorBrush() 上都会抛出异常:

The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

在最近的更改之前,我在 x:Bind 中使用 Conveter 来完成 GetForegroundColor 方法正在做的工作(由于转换器会导致性能下降,我决定更改该方法) - 它工作得很好。我还更新了一些其他数据绑定属性 - 更新 UI(代码省略),这工作得很好。

任何想法都将不胜感激。这让我发疯了。

【问题讨论】:

  • 您需要在 UI Thread 中调用该方法(我需要在使用 UWP 时在 Xamarin Forms 上执行相同操作)
  • 感谢您的评论。这是我的问题的根源:所以我正在更新包装在 Despatcher 调用中的模型,然后触发模型内部的调用 CollectionChanged 事件处理程序。是否在不同的线程上调用了 CollectionChanged 事件,因为对更新模型类的原始调用是在 UI 线程上进行的。

标签: c# multithreading xaml uwp


【解决方案1】:

您需要在主线程上运行模型的更改。 我在使用 MVVM 的 UWP 中遇到了同样的问题。

我认为您需要使用调度程序包装您的事件处理程序代码,以便在 UI 线程上运行它。

private void TrolleyAllocations_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
      Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
      {
           RaisePropertyChanged("WorkOrderLineItems");
           ForegroundColor = GetForegroundColour();
      }
}

现在您的处理程序被调用并从后台任务中触发,因此GetForegroundColor() 在同一个线程上。

【讨论】:

    猜你喜欢
    • 2023-03-20
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    • 2018-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-05
    相关资源
    最近更新 更多