Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 调用线程无法访问此对象,因为存在其他线程_C#_Winforms - Fatal编程技术网

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控件: