从不同的线程并发地在DataSet中添加和删除行
本文关键字:DataSet 添加 删除行 线程 并发 | 更新日期: 2023-09-27 17:54:48
我以为我知道lock
语句是如何工作的,但似乎我不知道……我试图实现的功能,使我能够添加和删除行/从DataSet
从单独的线程并发(WinForms项目)。因此,一个线程每隔一段时间间隔向DataSet
添加新行,而另一个线程从相同的DataSet
删除行。我假设DataSet
总是有一些行要删除-我想在这里关注多线程问题。添加行到DataSet
的线程比删除行更快。对于创建新线程,我使用System.Threading.Timer
类,它在创建新实例时启动新线程。我不明白为什么我仍然得到System.InvalidOperationException
,而在我的代码中有lock
语句。进一步的消息是:"附加信息:检测到交叉线程操作。"
如何使用lock
语句?我到底应该把lock
语句在我的代码?
using System;
using System.Data;
using System.Threading;
using System.Windows.Forms;
namespace TEST_WinForms
{
public partial class Form1 : Form
{
private const String _strDSname = "dataSet";
private const String _strTableName = "dtBuffer";
private object _objLockDataSet = new object();
public Form1()
{
InitializeComponent();
}
private void BuildDataSet()
{
DS = new DataSet();
DS.Tables.Add(_strTableName);
foreach (DataTable table in DS.Tables)
{
table.Columns.Add("LP", typeof(Int32));
table.Columns.Add("Date and time", typeof(DateTime));
}
}
private void StartT1timer()
{
try
{
if (T1 == null)
{
T1 = new System.Threading.Timer(new TimerCallback(AddRow)
, null
, 0
, Timeout.Infinite);
}
else
{
T1.Change(0, Timeout.Infinite);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void StartT2timer()
{
try
{
if (T2 == null)
{
T2 = new System.Threading.Timer(new TimerCallback(DeleteRow)
, null
, 1000
, Timeout.Infinite);
}
else
{
T2.Change(1000, Timeout.Infinite);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void AddRow(object state)
{
lock (_objLockDataSet)
{
try
{
this.Invoke(new MethodInvoker(() =>
{
DataRow newRow = DS.Tables[_strTableName].NewRow();
if (DS.Tables[_strTableName].Rows.Count > 0)
{
newRow["LP"] =
(int)DS.Tables[_strTableName].Rows[DS.Tables[_strTableName].Rows.Count - 1]["LP"] + 1;
}
else
{
newRow["LP"] = 1;
}
newRow["Date and time"] = DateTime.Now;
DS.Tables[_strTableName].Rows.Add(newRow);
}));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
T1.Change(100, Timeout.Infinite);
}
private void DeleteRow(object state)
{
try
{
lock (_objLockDataSet)
{
if (DS.Tables[_strTableName].Rows.Count > 0)
{
DS.Tables[_strTableName].Rows.RemoveAt(0);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
T2.Change(500, Timeout.Infinite);
}
private void Form1_Load(object sender, EventArgs e)
{
BuildDataSet();
gridControl1.DataSource = DS.Tables[_strTableName];
StartT1timer();
StartT2timer();
}
private DataSet DS
{
get;
set;
}
private System.Threading.Timer T1
{
get;
set;
}
private System.Threading.Timer T2
{
get;
set;
}
}
}
问题不在于lock
语句,而在于从非UI线程的线程访问UI控件(从数据源中删除行)。
实际上你在添加行时这样做是正确的,所以在删除时也这样做-使用表单的Invoke
方法以便在正确的线程上执行委托