我已经阅读了许多关于线程的解释,但我仍然很难掌握。我在我的代码中尝试了它,我得到一个错误:“附加信息:跨线程操作无效:控制'dgvLocDatabase'从一个线程访问,而不是在上创建的线程。下面是我创建的代码。它必须将来自不同源的数据添加到2个不同的datagridview。
private void btnCountRecord_Click(object sender, EventArgs e)
{
CountRecord();
Parallel.Invoke(
GetDevData,
GetPcData
);
}
private void GetDevData()
{
if (bIsConnected == false)
{
MessageBox.Show(@"Please connect the device first", @"Error");
return;
}
var sdwEnrollNumber = "";
var idwTMachineNumber = 0;
var idwEMachineNumber = 0;
var idwVerifyMode = 0;
var idwInOutMode = 0;
var idwYear = 0;
var idwMonth = 0;
var idwDay = 0;
var idwHour = 0;
var idwMinute = 0;
var idwSecond = 0;
var idwWorkcode = 0;
var idwErrorCode = 0;
var iGlCount = 0;
var iIndex = 0;
dgvDevDatabase.Rows.Clear();
axCZKEM1.EnableDevice(iMachineNumber, false); //disable the device
if (axCZKEM1.ReadGeneralLogData(iMachineNumber)) //read all the attendance records to the memory
{
lblProgressBar.Text = @"Loading data. Please wait...";
progBar.Visible = true;
progBar.Maximum = _gRecCount;
progBar.Minimum = 1;
progBar.Value = 1;
progBar.Step = 1;
while (axCZKEM1.SSR_GetGeneralLogData(iMachineNumber, out sdwEnrollNumber, out idwVerifyMode,
out idwInOutMode, out idwYear, out idwMonth, out idwDay, out idwHour, out idwMinute, out idwSecond, ref idwWorkcode))//get records from the memory
{
iGlCount++;
var bioId = sdwEnrollNumber;
var timeLog = idwYear + "-" + idwMonth + "-" + idwDay + " " + idwHour + ":"
+ idwMinute + ":" + idwSecond;
dgvDevDatabase.Rows.Add(bioId, timeLog);
progBar.PerformStep();
}
if (progBar.Value == _gRecCount) lblProgressBar.Text = @"";
}
else
{
Cursor = Cursors.Default;
axCZKEM1.GetLastError(ref idwErrorCode);
if (idwErrorCode != 0)
{
MessageBox.Show(@"Reading data from device failed. ErrorCode: " + idwErrorCode, @"Error");
}
else
{
MessageBox.Show(@"No data from terminal to return", @"Error");
}
}
axCZKEM1.EnableDevice(iMachineNumber, true);//enable the device
}
private void GetPcData()
{
var tda = new TimeLogDataAccess();
_rdr = tda.GetAllLogs();
while (_rdr.HasRows && _rdr.Read())
{
dgvLocDatabase.Rows.Add(_rdr["bio_id"].ToString(), _rdr["time_log"].ToString());
}
}
如果我从Parallel.Invoke中删除“GetPcData”并将其替换为Messagebox.Show(“Call me too”);,我不会收到错误,如果我只是自己运行“GetPcData” ,我也没有得到错误。所以我认为这是导致问题的Parallel.Invoke中的“GetPcData”。
你能否告诉我我做错了什么,如果你能向我解释这个parallel.invoke或线程。谢谢。
答案 0 :(得分:0)
问题是,您正在尝试修改线程以外的线程中的UI,UI是从中创建的。 查看SynchronizationContext类(https://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext(v=vs.110).aspx)并尝试以下操作: 在调用新线程分配之前 SynchronizationContext.Current 变量。然后启动新线程,如果要更新UI,请通过调用
来执行此操作myContext.Post(cb => { doSomethingOnUi(); }, null);
并查看是否可以解决您的问题。