在发布问题之前,我做了10天的研究,所以真的希望有人可以解决这个问题。
问题是任何可绑定控件一旦更改了singleton类的绑定列表就不会更新。这是多线程应用程序的常见问题。大多数(如果不是全部)解决方案提供了从父线程初始化bindlinglist或集合的建议,然后进行了一些调用。不是我想要的。如果使用静态类而不是单例,则同样的问题仍然存在。
基本上,应用程序会触发一些任务,这些任务又会在不同的业务类上创建对象。这些对象将消息发布到绑定列表中,该列表应更新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);
}
}
}
的Singleton:
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();
}
答案 0 :(得分:1)
您的问题是制作列表框的线程(主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; }
}
}
}