0

I've been working on a C# WinForm project that has a part in which when a user keys up "enter" button, a BackgroundWorker will set a new URI in the Source property of the Awesomium Instance. However, I'm encountering an AweInvalidOperationException ("The calling thread cannot access this object because a different thread owns it.").

Here's a sample code of a part of my work:

private void txt_To_KeyUp(object sender, KeyEventArgs e)
{
   if (e.KeyCode == Keys.Enter)
   {
   backgroundWorker.RunWorkerAsync();
   }
}

private void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
  //Get values from an XML file and everything (Not included here anymore for it's too long)
  awesomiumInstance.Source = new Uri("http://maps.google.com?saddr=" +
                             txt_From.Text.Replace(" ", "+") + "&daddr=" +                                  txt_To.Text.Replace(" ", "+") + flag +
                             "&view=map&hl=en&doflg=ptk");
}


The AweInvalidOperationException happens at line 12

awesomiumInstance.Source = new Uri("http://maps.google.com?saddr=" +
                           txt_From.Text.Replace(" ", "+") + "&daddr=" +
                           txt_To.Text.Replace(" ", "+") + flag +
                           "&view=map&hl=en&doflg=ptk");


Here's the screenshot of the exception:

AweInvalidOperationException Screenshot

What could be the fix/solution to this exception?

Jimwel Anobong
  • 468
  • 5
  • 18

1 Answers1

1

You need to invoke the code on the UI Thread, since you are not using WPF you don't have the Dispatcher, however you can try Invoke or BeginInvoke like the following

        this.BeginInvoke((Action)(() =>
        {
            awesomiumInstance.Source = new Uri("http://maps.google.com?saddr=" +
                            txt_From.Text.Replace(" ", "+") + "&daddr=" +
                            txt_To.Text.Replace(" ", "+") + flag +
                            "&view=map&hl=en&doflg=ptk");
        }));

Invoke causes the action to execute on the thread that created the Control's window handle. BeginInvoke is the Asynchronous version of Invoke which means the thread will not block the caller as unlike the synchronous call which is blocking.

If that doesn't work you can then use the SynchronizationContext

EDIT: Post is Asynchronous

        SynchronizationContext.Current.Post(_ =>
        {
            awesomiumInstance.Source = new Uri("http://maps.google.com?saddr=" +
                            txt_From.Text.Replace(" ", "+") + "&daddr=" +
                            txt_To.Text.Replace(" ", "+") + flag +
                            "&view=map&hl=en&doflg=ptk");
        }, null);

SynchronizationContext assists you in executing code on the UI Thread where necessary, Delegates that are passed to its Send or Post method will then be invoked in that location. (Post is the non-blocking of Send.) For a more detailed explanation please visit This Link

If SynchronizationContext.Current is null then check this link when and when not it is null

Community
  • 1
  • 1
Donald Jansen
  • 1,937
  • 4
  • 22
  • 41
  • to which method am I going to include these blocks? Gonna give it a try after you answer. – Jimwel Anobong Apr 14 '17 at 17:03
  • You can add that code inside of your `backgroundWorker_DoWork` method – Donald Jansen Apr 14 '17 at 17:04
  • Can I request a more detailed explanation of your answer for to me know not just use it. It would be a great knowledge worth remembering if you don't mind. (Please explain what's the use of `SynchronizationContext.Current.Send` or explain what does it do.) – Jimwel Anobong Apr 14 '17 at 17:07
  • Sure no problem, I always give the code first then explain it all in detail – Donald Jansen Apr 14 '17 at 17:09
  • I accepted your answer because the first one works. However, I'm concerned with the second option which is `SynchronizationContext.Current.Post(...`. It throws a NullReferenceException, maybe because of the null found at the latter part of the code. What can I substitute to fix the second option? – Jimwel Anobong Apr 14 '17 at 17:17
  • 1
    There is a reason for that, `SynchronizationContext.Current` propably was null and the reason for that is a bit strange but I updated the answer with a link that explains when and when not it will be `null` – Donald Jansen Apr 14 '17 at 17:23