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

多UI线程与数据绑定问题求助:跨线程UI更新异常

多UI线程场景下的BindingList与UI同步更新问题

场景说明

应用程序为每个窗体启动独立UI线程,以此提升循环更新性能并支持模态弹窗(如选择值后打开窗体)。但单UI线程的SynchronizationContext无法适配该架构,导致UI更新出现问题。

现有实现代码

1. ApplicationContext中多线程启动窗体

public AppContext()
{
    foreach(var form in activeForms)
    {
        form.Load += Form_Load;
        form.FormClosed += Form_FormClosed;
        StartFormInSeparateThread(form);
        //form.Show();
    }
}
private void StartFormInSeparateThread(Form form)
{
    Thread thread = new Thread(() =>
    {
        Application.Run(form);
    });
    thread.ApartmentState = ApartmentState.STA;
    thread.Start();
}

2. 尝试实现的多UI线程安全BindingList

List<SynchronizationContext> listctx = new();

public ThreadSafeBindingList2()
{
    //SynchronizationContext ctx = SynchronizationContext.Current;
    //listctx.Add(ctx);
}
public void SyncContxt()
{
    SynchronizationContext ctx = SynchronizationContext.Current;
    listctx.Add(ctx);
}
protected override void OnAddingNew(AddingNewEventArgs e)
{
    for (int i = 0; i < listctx.Count; i++)
    {
        if (listctx[i] == null)
        {
            BaseAddingNew(e);
        }
        else
        {
            listctx[i].Send(delegate
            {
                BaseAddingNew(e);
            }, null);
        }
    }
}
void BaseAddingNew(AddingNewEventArgs e)
{ 
    base.OnAddingNew(e); 
}

protected override void OnListChanged(ListChangedEventArgs e)
{
    for (int i = 0; i < listctx.Count; i++)
    {
        if (listctx[i] == null)
        {
            BaseListChanged(e);
        }
        else
        {
            listctx[i].Send(delegate
            {
                BaseListChanged(e);
            }, null);
        }
    }
}

void BaseListChanged(ListChangedEventArgs e)
{
    base.OnListChanged(e); 
} 

3. 静态数据更新中心(含BackgroundWorker)

private static void BackgroundWorker_DoWork(object? sender, DoWorkEventArgs e)
{
    if (timerStart is false)
    {
        Thread.Sleep(6000);
        timerStart = true;
    }
    while (DisplayTimerUpdateBGW.CancellationPending is false)
    {
        threadSleepTimer = OrderList.Where(x => x.Status != OrderOrderlineStatus.Claimed).ToList().Count > 20 ? 2000 : 1000;
        if (OrderList.Count > 40)
            threadSleepTimer = 3000;

        UpdateDisplayTimer();

        Thread.Sleep(threadSleepTimer);
    }
} 
private static void UpdateDisplayTimer()
{
    var displayLoopStartTimer = DateTime.Now;
    TimeSpan displayLoopEndTimer = new();

    Span<int> orderID = CollectionsMarshal.AsSpan(OrderList.Select(x => x.ID).ToList());
    for (int i = 0; i < orderID.Length; i++)
    {
        OrderModel order = OrderList[i];
        order.OrderInfo = "Ble";
        Span<int> OrderLineID = CollectionsMarshal.AsSpan(order.Orderlines.Select(x => x.Id).ToList());
        for (int j = 0; j < OrderLineID.Length; j++)
        {
            OrderlineModel ol = order.Orderlines[j];
            TimeSpan TotalElapsedTime = ol.OrderlineCompletedTimeStamp != null ? (TimeSpan)(ol.OrderlineCompletedTimeStamp - ol.OrderlineReceivedTimeStamp) : DateTime.Now - ol.OrderlineReceivedTimeStamp;
            string displaytimerValue = "";

            if (ol.OrderlineCompletedTimeStamp == null)
                displaytimerValue = TotalElapsedTime.ToString(@"mm\:ss");
            else
                displaytimerValue = $" {(DateTime.Now - ol.OrderlineCompletedTimeStamp)?.ToString(@"mm\:ss")} \n({TotalElapsedTime.ToString(@"mm\:ss")})";

            ol.DisplayTimer = displaytimerValue;

        }
    }
}

需求

所有窗体的Label和DataGridView均绑定同一BindingList,希望借助INotifyPropertyChanged实现所有UI线程中的属性同步更新,寻求可行解决方案。


内容的提问来源于stack exchange,提问作者Ifirit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 01:31:04