在做界面程序时,常常需要一些数据类,界面元素通过绑定等方式显示出数据,然而由于UI线程不是线程安全的,一般都需要通过Invoke等方式来调用界面控件。但对于数据绑定bindingList而言,没法响应listchang事件,导致后端的grid等控件不能更新数据。废了好大的劲终于找到一个UIBindingList,实现线程数据的同步!
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms; namespace TempForms
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent(); Initial();
} private UiBindList<int> _list;
private void Initial()
{
_list = new UiBindList<int> { SynchronizationContext = SynchronizationContext.Current };
bindingSource1.DataSource = _list; new Thread(() =>
{
while (true)
{
Thread.Sleep(1000);
var newItem = DateTime.Now.Second;
_list.Add(newItem); Thread.Sleep(1000);
_list.Remove(newItem);
}
})
{
IsBackground = true,
}
.Start();
}
} /// <summary>
/// 扩展BindingList,防止增加、删除项时自动更新界面而不出现“跨线程操作界面控件”异常
/// </summary>
class UiBindList<T> : BindingList<T>
{
/// <summary>
/// 界面同步上下文
/// </summary>
public SynchronizationContext SynchronizationContext { get; set; } /// <summary>
/// 使用此方法执行一切操作上下文相关的操作
/// </summary>
private void Excute(Action action, object state = null)
{
if (SynchronizationContext == null)
action();
else
SynchronizationContext.Post(d => action(), state); } public new void Add(T item)
{
Excute(() => base.Add(item));
} public new void Remove(T item)
{
Excute(() => base.Remove(item));
}
}
}