C# 调用线程无法访问此对象,因为存在其他线程
每次我尝试设置任何标签文本属性时,它都会抱怨不在同一个线程中。这有点令人困惑,因为代码在事件处理程序中 同样适用于C# 调用线程无法访问此对象,因为存在其他线程,c#,winforms,C#,Winforms,每次我尝试设置任何标签文本属性时,它都会抱怨不在同一个线程中。这有点令人困惑,因为代码在事件处理程序中 同样适用于pictureBox 如何对其进行修改以使其按预期工作 public partial class Form3 : Form { AttendanceControlDevice control; public Form3() { InitializeComponent(); } private void Form3_Load(
pictureBox
如何对其进行修改以使其按预期工作
public partial class Form3 : Form
{
AttendanceControlDevice control;
public Form3()
{
InitializeComponent();
}
private void Form3_Load(object sender, EventArgs e)
{
string conn = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
control = new AttendanceControlDevice(new EmployeesRepository(new SqlConnection(conn)), new zkemkeeper.CZKEMClass());
control.OnEmployeeChecked += new EventHandler<EmployeeCheckedEventArgs>(control_OnEmployeeChecked);
control.Connect(ConfigurationManager.AppSettings["ip"], int.Parse(ConfigurationManager.AppSettings["port"]));
}
void control_OnEmployeeChecked(object sender, EmployeeCheckedEventArgs e)
{
try
{
label1.Text = e.Employee.Id;
label2.Text = e.Employee.Name;
pictureBox1.Image = Image.FromFile(e.Employee.Picture);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
public class AttendanceControlDevice
{
...
public bool Connect(string ip,int port)
{
_connected = _commChannel.Connect_Net(ip, port);
if(!_connected)
{
_commChannel.GetLastError(ref _lastError);
Error = _errorDescriptions[_lastError];
}else{
_commChannel.RegEvent(1, (int)deviceEvents.OnAttTransaction);
_commChannel.OnAttTransactionEx += new zkemkeeper._IZKEMEvents_OnAttTransactionExEventHandler(commChannel_OnAttTransactionEx);
}
return _connected;
}
void commChannel_OnAttTransactionEx(string EnrollNumber, int IsInValid, int AttState, int VerifyMethod, int Year, int Month, int Day, int Hour, int Minute, int Second, int WorkCode)
{
if(OnEmployeeChecked != null)
{
Employee employee = null;
try{
employee = _employees.Get(EnrollNumber);
}
catch {
employee = new Employee(EnrollNumber, "Error while reading the data", "");
}
if (employee == null) employee = new Employee(EnrollNumber, "Could not match the id", "");
OnEmployeeChecked.Invoke(this, new EmployeeCheckedEventArgs(employee));
}
}
公共部分类表单3:表单
{
注意力控制;
公共表格3()
{
初始化组件();
}
私有void Form3_加载(对象发送方、事件参数e)
{
字符串conn=ConfigurationManager.ConnectionString[“connStr”].ConnectionString;
control=new AttendanceControl(new EmployeesRepository(new SqlConnection(conn)),new zkemkeeper.CZKEMClass());
control.OnEmployeeChecked+=新事件处理程序(control\u OnEmployeeChecked);
control.Connect(ConfigurationManager.AppSettings[“ip”]、int.Parse(ConfigurationManager.AppSettings[“端口”]);
}
无效控制\u OneEmployeeChecked(对象发送方、EmployeeCheckedEventArgs e)
{
尝试
{
label1.Text=e.Employee.Id;
label2.Text=e.Employee.Name;
pictureBox1.Image=Image.FromFile(e.Employee.Picture);
}
捕获(例外情况除外)
{
Show(例如ToString());
}
}
}
公共课堂出席人数控制
{
...
公共布尔连接(字符串ip,int端口)
{
_已连接=\通信信道。连接\网络(ip,端口);
如果(!\u已连接)
{
_commChannel.GetLastError(参考_lastError);
错误=_errorDescriptions[_lastError];
}否则{
_commChannel.RegEvent(1,(int)deviceEvents.OnAttTransaction);
_commChannel.OnAttTransactionEx+=新ZKEMKEEP.\u IZKEMEvents\u OnAttTransactionExEventHandler(commChannel\u OnAttTransactionEx);
}
返回连接;
}
无效通信信道\u OnAttTransactionEx(字符串编号、int-IsInValid、int-AttState、int-VerifyMethod、int-Year、int-Month、int-Day、int-Hour、int-Minute、int-Second、int-WorkCode)
{
if(OnEmployeeChecked!=null)
{
Employee=null;
试一试{
employee=\u employees.Get(注册号);
}
捕获{
employee=新员工(注册号,“读取数据时出错”,为“”);
}
如果(employee==null)employee=new employee(注册号,“无法匹配id”,”);
调用(这是新的EmployeeCheckedEventArgs(employee));
}
}
}我的猜测是AttendanceControl正在后台线程上引发事件,或者(更可能)存储库正在后台线程上引发某个事件,并且该事件正在通过AttendanceControl传播,因此当事件触发时,您仍在后台线程上
您可能知道这一点,但应该检查InvokeRequired并适当地调用/BeginInvoke。这可能是因为AttendanceControl上的线程与当前线程不同
在这种情况下,您应该对Windows窗体控件进行线程安全调用,正如您所知(MSDN链接:)实际上我不知道…:Czkemp类是用于与某些设备通信的第三方库。AttendanceControl只订阅某些事件,然后触发自己的事件。我更新了帖子来说明这一点。您添加的代码加深了(但没有证实)我对AttendanceControl事件在后台线程上的怀疑,因为引发它的上游代码正在后台线程上运行。请参见此处,了解如何从后台线程安全地调用UI控件: