Search code examples
c#winformsexceptionc#-4.0awesomium

Awesomium in C# Exception Fix?


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?


Solution

  • 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