任务/多线程时的单例可绑定控件

本文关键字:单例可 绑定 控件 多线程 任务 | 更新日期: 2023-09-27 18:02:10

在发布这个问题之前,我做了10天的研究,所以真的希望有人能给解决这个问题一些启示。

问题是任何可绑定的控件,在单例类的绑定列表被更改后都不会更新。这是多线程应用的常见问题。大多数(如果不是所有)解决方案都提供了建议,其中从父线程初始化bindlinglist或集合,然后进行一些调用。不是我想要的。如果使用静态类而不是单例,同样的问题仍然存在。

基本上,应用程序触发一些任务,这些任务依次在不同的业务类上创建对象。这些对象将消息发送到bindinglist中,bindinglist应该更新UI列表框,但是没有。是的,消息对象在列表中,并且在之后绑定 TASK完成工作(项目显示)。锁定/解锁对象访问也不是问题。

感谢您的建议/解决方案

业务对象的精简版本:

namespace MyNameSpace
{
    public class Message
    {
        private string messageSummary;
        public Message() { }
        public string MessageSummary
        {
            set { messageSummary = value; }
            get { return messageSummary; }
        }
    }
}

另一个类做一些操作的精简版本:

namespace MyNameSpace
{
    public class WorkDoingClass
    {
        public WorkDoingClass() { }
        public void DoSomeWork()
        {
            //some routines
            Message messageObj = new Message();
            messageObj.MessageSummary = "DoSOmrWork Finished";
        }
        public void DoSomeOtherWork()
        {
            //some routines
            Message messageObj = new Message();
            messageObj.MessageSummary = "DoSomeOtherWork Finished";
            AllMessages.Instance.AllMessagesBindingList.Add(messageObj);
        }
    }
}

单:

namespace MyNameSpace
{
    public sealed class AllMessages
    {
        private static readonly AllMessages _instance = new AllMessages();
        private BindingList<Message> _allMessagesBL;
        public WorkDoingClass() { _allMessagesBL = new BindingList<Message>(); }
        public static AllMessages Instance
        {
            get { return _instance; }
        }
        public BindingList<Message> AllMessagesBindingList
        {
            get { return _allMessagesBL};
        }
    }
}

这也是一个精简版本,从调用开始:

namespace MyNameSpace
{
    public partial class Form1 : Form
    {
        private Task _TaskSqlData;
        private CancellationTokenSource cTokenSourceSql;
        public Form1()
        {
            InitializeComponent();
            listBox1.DataSource = AllMessages.Instance.AllMessagesBindingList;
            listBox1.DisplayMember = "MessageSummary";
        }
    private void button1_Click(object sender, EventArgs e)
    {
            cTokenSourceSql = new CancellationTokenSource();
            var tokenSqlData = cTokenSourceSql.Token;
            if (this._TaskSqlData != null)
            {
                if (this._TaskSqlData.Status == TaskStatus.Running)
                    this.cTokenSourceSql.Cancel();
                this._TaskSqlData.Dispose();
                this._TaskSqlData = null;
            }
            _TaskSqlData = Task.Factory.StartNew(()
                            => StartDoingWork(this, tokenSqlData, null), tokenSqlData);
    }
    public void StartDoingWork(object sender, CancellationToken ct, EventArgs e)
    {
            if (ct.IsCancellationRequested)
                ct.ThrowIfCancellationRequested();
            WorkDoingClass work = new WorkDoingClass();
            work.DoSomeOtherWork();
    }

任务/多线程时的单例可绑定控件

你的问题是创建列表框的线程(主UI线程)与修改集合的线程(工作线程)不同。

试试下面的代码。它可以解决你的问题。我使用SynchronizationContext来同步两个线程,它作为Control.Invoke()的相同函数。

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private Task _TaskSqlData;
        private CancellationTokenSource cTokenSourceSql;
        WorkDoingClass _work;
        public Form1()
        {
            InitializeComponent();
            listBox1.DataSource = AllMessages.Instance.AllMessagesBindingList;
            listBox1.DisplayMember = "MessageSummary";
            _work = new WorkDoingClass(SynchronizationContext.Current);
        }
        private void button1_Click(object sender, EventArgs e)
        {
            cTokenSourceSql = new CancellationTokenSource();
            var tokenSqlData = cTokenSourceSql.Token;
            if (this._TaskSqlData != null)
            {
                if (this._TaskSqlData.Status == TaskStatus.Running)
                    this.cTokenSourceSql.Cancel();
                this._TaskSqlData.Dispose();
                this._TaskSqlData = null;
            }
            _TaskSqlData = Task.Factory.StartNew(()
                            => StartDoingWork(this, tokenSqlData, null), tokenSqlData);
        }
        public void StartDoingWork(object sender, CancellationToken ct, EventArgs e)
        {
            if (ct.IsCancellationRequested)
                ct.ThrowIfCancellationRequested();
            _work.DoSomeOtherWork();
        }
    }
    public class Message
    {
        private string messageSummary;
        public Message() { }
        public string MessageSummary
        {
            set { messageSummary = value; }
            get { return messageSummary; }
        }
    }
    public class WorkDoingClass
    {
        private SynchronizationContext _syncContext;
        public WorkDoingClass() { }
        public WorkDoingClass(SynchronizationContext _syncContext)
        {
            // TODO: Complete member initialization
            this._syncContext = _syncContext;
        }
        public void DoSomeWork()
        {
            //some routines
            Message messageObj = new Message();
            messageObj.MessageSummary = "DoSOmrWork Finished";
        }
        public void DoSomeOtherWork()
        {
            _syncContext.Send(DoWork, null);
        }
        private static void DoWork(object arg)
        {
            //some routines
            Message messageObj = new Message();
            messageObj.MessageSummary = "DoSomeOtherWork Finished";
            AllMessages.Instance.AllMessagesBindingList.Add(messageObj);
        }
    }
    public sealed class AllMessages
    {
        private static readonly AllMessages _instance = new AllMessages();
        private BindingList<Message> _allMessagesBL;
        public AllMessages() { _allMessagesBL = new BindingList<Message>(); }
        public static AllMessages Instance
        {
            get { return _instance; }
        }
        public BindingList<Message> AllMessagesBindingList
        {
            get { return _allMessagesBL; }
        }
    }
}