2011-09-06 37 views
0

每次我尝试设置任何标签文本属性时,它都会抱怨说不在同一个线程中。这有点令人困惑,因为代码是在一个事件处理程序中。调用线程不能访问此对象,因为不同的线程

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)); 
     } 
    } 

}

回答

2

我的猜测是,AttendanceControlDevice是引发事件的后台线程,或(更可能)存储库是提高在后台线程上的一些事件,并且通过AttendanceControlDevice传播和因此当事件触发时您仍然处于后台线程。

你可能知道这一点,但你应该适当地检查InvokeRequired和Invoke/BeginInvoke。

+0

其实我不知道...:P 的CZKEMClass这是第三用于与某些设备进行通信的第三方库。 AttendanceControlDevice只是订阅某些事件,然后触发它自己的事件。我更新了帖子以表明这一点。 – max

+0

您添加的代码加深了(但不确认)我对AttendanceControlDevice处于后台线程的事件的怀疑,因为引发它的上游代码正在后台线程上运行。请参阅这里了解如何从后台线程安全地调用UI控件:http://msdn.microsoft.com/en-us/library/ms171728%28v=vs.80%29.aspx –

相关问题