title: Access object in a different thread
body: <p><strong>Setup:</strong></p>
  
  <p>Win10 .NET 4.7.1/VS2017 .NET 4.5/ C#</p>
  
  <p><strong>Level:</strong></p>
  
  <p>Beginner/Intermediate/new to threading</p>
  
  <p><strong>Objective:</strong></p>
  
  <p>1: A selenium web automation class that is triggered by a timer class so that the web automation class can exchange data with a javascript site at specific times.</p>
  
  <p>2: Should be possible to migrate solution from WebForms to .NET library (dll).</p>
  
  <p><strong>Problem:</strong></p>
  
  <p>Step 1. Timer class sends time event to method in Web class to login to internet site = working.</p>
  
  <p>Step 2. Web automation class (WinForms/GUI) tries to retrieve data from the method that is triggered by timer class event = Exception: "Calling thread cannot access this object because a different thread owns it." (as translated from swe).</p>
  
  <p>I admit I´m confused by the terminology in the area of threading that is new to me. Also, I understand some multithreading techniques are only valid for WinForms. Since my objective is to migrate the solution to a dll these are not an option for me. I´ve played around with Invoke(), but as I understand it´s limited to use in WinForms. Guidance is highly appreciated!</p>
  
  <p>WEB AUTOMATION CLASS:</p>
  
  <pre><code>    private EdgeDriver driver;
      private SeleniumHelper helper;
      private WebAutomationTimer timer;
      private double account;
  
      public double Account { get =&gt; this.account; set =&gt; this.account = value; }
  
      public Form1()
      {
          InitializeComponent();
          timer = new WebAutomationTimer(02, 36, 00, 02, 38, 00);
          timer.OnLoginTime += Timer_OnLoginTime;
          timer.OnLogoutTime += Timer_OnLogoutTime;
      }
  
      private void Timer_OnLoginTime()
      {
          Login();
      }
  
      private void Timer_OnLogoutTime()
      {
          Logout();
      }
  
      public bool Login()
      {
          try
          {
              // working login code
  
      UpdateLabels();
          }
          catch (Exception e)
          {
  
          }
      }
  
      private void UpdateLabels()
      {
          // EXCEPTION !!!
          lblAccount.Text = GetAccount(); 
      // EXCEPTION !!!
      }
  </code></pre>
  
  <p>TIMER CLASS:</p>
  
  <pre><code>class WebAutomationTimer
  {
      public event TimerEvent OnLoginTime;
      public event TimerEvent OnLogoutTime;
      //public event TimerEvent OnSecond;
      private System.Timers.Timer timer;
      private DateTime now;
      private int loginHour;
      private int loginMin;
      private int loginSec;
      private int logoutHour;
      private int logoutMin;
      private int logoutSec;
  
      public WebAutomationTimer(int loginHour, int loginMin, int loginSec, int logoutHour, int logoutMin, int logoutSec)
      {
          timer = new System.Timers.Timer();
          timer.Interval = 1000; // 1 sec
          timer.Elapsed += Timer_Elapsed;
          timer.Start();
          this.loginHour = loginHour;
          this.loginMin = loginMin;
          this.loginSec = loginSec;
          this.logoutHour = logoutHour;
          this.logoutMin = logoutMin;
          this.logoutSec = logoutSec;
      }
  
      // Each second event
      private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
      {
          now = DateTime.Now;
          //OnSecond();
  
          //login
          if (now.Hour == loginHour &amp;&amp; now.Minute == loginMin &amp;&amp; now.Second == loginSec)
              OnLoginTime();
  
          //logout
          if (now.Hour == logoutHour &amp;&amp; now.Minute == logoutMin &amp;&amp; now.Second == logoutSec)
              OnLogoutTime();
      }
  }
  </code></pre>
  
  <p>}</p>