title: Use a referenced object across threads
body: <p>What I am doing is creating an object(A) that holds a reference to another object(B). The UI portion of my code holds those objects(A) in a BindingList that is used as the data source for a DevExpress grid view. The controller sends the newly created objects(A) to the UI via an event. The controller also has a thread that updates the referenced object(B). The exception thrown comes from the DevExpress GridView and reads "Cross thread operation detected. To suppress this exception, set DevExpress.Data.CurrencyDataController.DisableThreadingProblemsDetection = true".</p>
  
  <p>Now I don't want to suppress this exception because the code will eventually end up in a critical application. </p>
  
  <p>So how can I update a reference object across threads without causing problems? Here is the code from my Test application. It will be essentially the same in the actual program.</p>
  
  <p><strong>UPDATE</strong>
  The error in the UI was fixed by the answer from Nicholas Butler but now the exception has moved into the Employee class.  I have updated the code to reflect the changes.</p>
  
  <p>Here is my code</p>
  
  <p>*<em>UI *</em></p>
  
  <pre><code>    public partial class Form1 : Form
  {
      private BindingList&lt;IEmployee&gt; empList;
      EmployeeController controller;
      private delegate void AddEmployeInvoke(IEmployee employee);
      public Form1()
      {
          controller = new EmployeeController();
          controller.onNewEmployee += new EmployeeController.NewEmployee(controller_onNewEmployee);
          empList = new BindingList&lt;IEmployee&gt;();
          InitializeComponent();
      }
  
      void controller_onNewEmployee(IEmployee emp)
      {
          AddEmployee(emp);
      }
  
      private void AddEmployee(IEmployee empl)
      {
          if (InvokeRequired)
          {
              this.Invoke(new AddEmployeInvoke(AddEmployee), new Object[] {empl});
          }
          else
          {
               empList.Add(empl);
          }
      }
  
      private void Form1_Load(object sender, EventArgs e)
      {
          this.gridControl1.DataSource = empList;
          this.gridControl1.RefreshDataSource();
          controller.Start();
      }
   }
  </code></pre>
  
  <p><strong>Controller:</strong></p>
  
  <pre><code>    class EmployeeController
  {
      List&lt;IEmployee&gt; emps;
      Task empUpdater;
      CancellationToken cancelToken;
      CancellationTokenSource tokenSource;
      Pay payScale1;
      Pay payScale2;
  
      public EmployeeController()
      {
          payScale1 = new Pay(12.00, 10.00);
          payScale2 = new Pay(14.00, 11.00);
          emps = new List&lt;IEmployee&gt;();
      }
  
      public void Start()
      {
          empUpdater = new Task(AddEmployee, cancelToken);
          tokenSource = new CancellationTokenSource();
          cancelToken = tokenSource.Token;
          empUpdater.Start();
      }
  
      public bool Stop()
      {
          tokenSource.Cancel();
          while (!empUpdater.IsCompleted)
          { }
          return true;
      }
  
      private void AddEmployee()
      {
          IEmployee emp = new Employee("steve", ref payScale1);
          ThrowEmployeeEvent(emp);
          emps.Add(emp);
          emp = new Employee("bob", ref payScale2);
          ThrowEmployeeEvent(emp);
          emps.Add(emp);
          int x = 0;
  
          while (!cancelToken.IsCancellationRequested)
          {
              emp = new Employee("Emp" + x, ref payScale1);
              ThrowEmployeeEvent(emp);
              x++;
              emp = new Employee("Emp" + x, ref payScale2);
              ThrowEmployeeEvent(emp);
  
              Thread.Sleep(1000);
  
              payScale2.UpdatePay(10.0);
              payScale1.UpdatePay(11.0);
  
              Thread.Sleep(5000);
          }
      }
  
      private void ThrowEmployeeEvent(IEmployee emp)
      {
          if (onNewEmployee != null)
              onNewEmployee(emp);
      }
  
      public delegate void NewEmployee(IEmployee emp);
      public event NewEmployee onNewEmployee;
  }
  </code></pre>
  
  <p><strong>Employee Class: (Exception thrown in this class)</strong></p>
  
  <pre><code>    class Employee : IEmployee
  {
      private string _name;
      private double _salary;
      private Pay _myPay;
      public string Name 
      { 
          get { return _name; } 
          set { _name = value; 
              //if (PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs("Name")); 
              } 
      }        
      public double Salary
      {
          get { return _salary; }
      }
      int x = 1;
  
      public Employee(string name, ref Pay pay)
      {
          _myPay = pay;
         _myPay.PropertyChanged += new PropertyChangedEventHandler(_myPay_PropertyChanged);
         _salary = _myPay.Salary;
          Name = name;
      }
  
      void _myPay_PropertyChanged(object sender, PropertyChangedEventArgs e)
      {
          if (e.PropertyName == "Salary")
          {
              _salary = _myPay.Salary;
              if (this.PropertyChanged != null)
                  // exception thrown on the line below
                  this.PropertyChanged(this, new PropertyChangedEventArgs("Salary"));
          }
      }
  
      public void ChangeName()
      {
          Name = "Me " + x;
          x++;
      }
  
      public event PropertyChangedEventHandler PropertyChanged;
  }
  </code></pre>
  
  <p><strong>Employee Interface:</strong></p>
  
  <pre><code>    interface IEmployee : INotifyPropertyChanged
  {
      string Name { get; set; }
      double Salary { get;}
  }
  </code></pre>
  
  <p><strong>Pay Class:</strong></p>
  
  <pre><code>    class Pay : INotifyPropertyChanged
  {
      private double _salary;
      private double _bonus;
      public double Salary { get { return _salary; } set { _salary = value; if(PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs("Salary"));} }
      public double Bonus { get { return _bonus; } set { _bonus = value; if (PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs("Bonus")); } }
  
      public Pay(double salary, double bonus)
      {
          Salary = salary;
          Bonus = bonus;
      }
  
      public void UpdatePay(double salary)
      {
          Salary += salary;
          if (onChange != null)
              this.onChange();
      }
  
      public void UpdatePay(double salary, double bonus)
      {
          Salary += salary;
          Bonus += bonus;
  
          if (onChange != null)
              this.onChange();
      }
  
      public delegate void Change();
      public event Change onChange;
  
      public event PropertyChangedEventHandler PropertyChanged;
  }
  </code></pre>
  
  <p>I greatly appreciate any help. </p>