调用线程无法访问此对象,因为其他线程不同

时间:2011-09-06 00:21:56

标签: c# winforms

每当我尝试设置任何标签文本属性时,它都会抱怨不在同一个线程中。由于代码在事件处理程序中,所以有点令人困惑。

同样适用于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 个答案:

答案 0 :(得分:2)

我的猜测是AttendanceControlDevice在后台线程上引发事件,或者(更有可能)Repository在后台线程上引发一些事件并且通过AttendanceControlDevice传播,因此你仍然在后台线程上事件发生了。

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

答案 1 :(得分:0)

这可能是因为AttendanceControlDevice on的线程与当前线程不同。

在您知道的情况下,您应该在这种情况下对Windows窗体控件进行线程安全调用(MSDN链接:http://msdn.microsoft.com/en-us/library/ms171728.aspx