AlienJack / AlienUICore

1 stars 0 forks source link

update 里面的List 的处理有待优化 #1

Closed Bian-Sh closed 1 month ago

Bian-Sh commented 2 months ago
  1. 多线程中像这样访问List Action 可能存在死锁的情况
  2. 可能存在修改正在遍历中的 List 的情况 我建议是使用一个临时变量 List temp 中转一下?
            if (m_dispatchActions.Count > 0)
            {
                var actionsToInvoke = new List<Action>();
                lock (m_dispatchActions)
                {
                    // 使用临时列表来避免遍历期间修改集合
                    actionsToInvoke.AddRange(m_dispatchActions);
                    m_dispatchActions.Clear();
                }
                foreach (var action in actionsToInvoke)
                {
                    action.Invoke();
                }
            }

    https://github.com/AlienJack/AlienUICore/blame/66425c710fc5fee9206fb82e6f0e60da31fa2733/AlienUI/Runtime/Core/Engine.cs#L147

AlienJack commented 2 months ago

这个dispatchAction列表设计意图是用于非unity线程往unity线程中插入需要操作unity相关api的代码用的 所以不应该出现执行dispatch中的action时出现修改dispatchaction list的行为,这种情况下我更倾向于抛出异常

每次dispatchaction执行时,复制一个列表的开销过大

Bian-Sh commented 2 months ago

那你用 ConcurrentQueue 吧,反正你这种写法就是错误的

private ConcurrentQueue<Action> m_dispatchActions = new ConcurrentQueue<Action>();

public void Dispatch(Action action)
{
    m_dispatchActions.Enqueue(action);
}

private void LateUpdate()
{
    if (layoutTask.Count > 0)
    {
        foreach (UIElement element in layoutTask)
        {
            if (element.Rect == null) continue;
            if (element.TopParent == null) element.BeginLayout();
        }
        layoutTask.Clear();
        Canvas.ForceUpdateCanvases();
    }

    while (m_dispatchActions.TryDequeue(out var action))
    {
        action.Invoke();
    }
}
Bian-Sh commented 2 months ago

你还别说,我真有说错的地方,你这里没有用到lock,真可能不会死锁,但是这样还是危险的啊 毕竟可能存在不同线程同时操作 list 的情况

你看看这俩代码区别,为啥Unity要这么改呢? 首先,他有 lock ,你没有 其次,第二个版本中,他使用了中间列表转手了一下,你也没有 https://github.com/Unity-Technologies/UnityCsReference/blob/2018.2/Runtime/Export/UnitySynchronizationContext.cs https://github.com/Unity-Technologies/UnityCsReference/blob/2018.3/Runtime/Export/UnitySynchronizationContext.cs