You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Avalonia中从非UI线程向ObservableCollection添加元素致ListBox刷新异常

解决Avalonia中非UI线程更新ObservableCollection导致ListBox不刷新的问题

问题核心

ObservableCollection不是线程安全的,所有绑定到UI的ObservableCollection修改操作必须在UI线程执行。你之前尝试的Dispatcher.Invoke可能未正确包裹集合修改逻辑,或是存在其他线程安全隐患。

具体修复步骤

1. 确认FilteredFrames的类型

确保FilteredFrames是ObservableCollection而非普通List,这是UI自动刷新的基础:

public ObservableCollection<string> FilteredFrames { get; } = new ObservableCollection<string>();

2. 用Avalonia Dispatcher将集合修改调度到UI线程

把FilteredFrames.Add操作包裹在UI线程调度逻辑中,替换原直接添加代码:

// 修改AddFrame中的添加逻辑
if ((frame.m_can_id & GeneralInformation.FilterCryterium) == frame.m_can_id)
{
    // 调度到UI线程执行添加
    _ = Application.Current.Dispatcher.InvokeAsync(() => 
    {
        FilteredFrames.Add(frameToString);
        Console.WriteLine("lalalal");   
    });
}

若ViewModel无法直接访问Application.Current,可通过构造函数注入IDispatcher实现解耦,避免直接依赖Application。

3. 修复RecievedFrames的线程安全问题

RecievedFrames是Dictionary,非UI线程操作存在线程安全风险,需加锁保护所有读写操作:

private readonly object _frameLock = new object();

public void AddFrame(CANFrame frame, long timeStamp)
{
    string frameToString = frame.ToString();
    lock (_frameLock)
    {
        if (!RecievedFrames.ContainsKey(frame))
        {
            if ((frame.m_can_id & GeneralInformation.FilterCryterium) == frame.m_can_id)
            {
                _ = Application.Current.Dispatcher.InvokeAsync(() => 
                {
                    FilteredFrames.Add(frameToString);
                    Console.WriteLine("lalalal");   
                });
            }
            RecievedFrames.Add(frame, timeStamp);
        }
        else
        {
            if ((frame.m_can_id & GeneralInformation.FilterCryterium) == frame.m_can_id)
            {
                _ = Application.Current.Dispatcher.InvokeAsync(() => 
                {
                    FilteredFrames.Add(frameToString);
                    Console.WriteLine("lalalal");   
                });
            }
            RecievedFrames[frame] = timeStamp;
        }

        if (RecievedFrames.Count == 20000)
            RecievedFrames.Remove(RecievedFrames.First().Key);
    }
}

4. 移除不必要的OnPropertyChanged调用

ObservableCollection在添加/移除元素时会自动触发CollectionChanged事件,UI会监听该事件自动刷新,因此你手动调用的OnPropertyChanged("FilteredFrames")完全多余,可直接删除:

// 删除此行代码
// MainWindowViewModel.FramePreviewViewModel.OnPropertyChanged("FilteredFrames");

额外优化建议

若需频繁从非UI线程更新集合,建议先在后台线程批量收集待添加元素,再一次性调度到UI线程完成添加,减少UI线程调度次数,避免影响界面性能。

内容的提问来源于stack exchange,提问作者Patryk Orłowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:09:55