Welcome Guest Search | Active Topics | Sign In | Register

Webbrowser Threading issue Options
Rasmus
Posted: Monday, November 24, 2014 3:12:06 AM
Rank: Advanced Member
Groups: Member

Joined: 4/17/2014
Posts: 35
Hi

Could you explain a little bit the threading model behind invoking js function from C# code?
Like how should i structure the link and what i shouldn't do.

I'm using this helper method to communicate with page

Code: C#
public static void InvokeJs<T>(string id, string js, System.Action<T> callback)
            where T : class, IConvertible
        {
            WebControl browser = webControls[id] as WebControl;
            var call = browser.WebView.QueueScriptCall(js);
            var wait = call.WaitOne();

            var sresult = call.Result.ToString();
            if (callback != null)
            {
                callback((T)Convert.ChangeType(sresult, typeof(T)));
            }
        }


The problem what i'm faceing is that, the call.WaitOne() will not return some times or there is a huge time cap comparing with normal execution time. The problem is probably that, this code section is accessed by different threads.
eo_support
Posted: Monday, November 24, 2014 10:01:19 AM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,067
Hi,

You should not do that. EO.WebBrowser is designed as a single thread model because of the window handle and window messages involved. Specifically, the thread that calls WebView.Create (in a Windows Forms application you do not call WebView.Create explicitly, but it is called in UI thread during the control's creation) creates the underlying window handle, thus "owns" the WebView. Everything else must go through this thread (with a few exception, for example, Destroy can be called from a different thread). As such it will be better for you to route the asynchronously call yourself through the thread that owns the WebView. You can take a look of class System.Threading.SynchronizationContext. This class functions in both Windows Forms and WPF application. It might help you to re-route the call through the UI thread.

Thanks!
Rasmus
Posted: Tuesday, November 25, 2014 5:14:33 AM
Rank: Advanced Member
Groups: Member

Joined: 4/17/2014
Posts: 35
Thank you for the instructions. So when i use the browser's dispatcher, everything should be fine?

Code: C#
public static void InvokeJs<T>(string id, string js, System.Action<T> callback)
            where T : class, IConvertible
        {
            WebControl browser = webControls[id] as WebControl;
            browser.Dispatcher.Invoke(() =>
            {
                var call = browser.WebView.QueueScriptCall(js);
                var wait = call.WaitOne();

                var sresult = call.Result.ToString();
                if (callback != null)
                {
                    callback((T)Convert.ChangeType(sresult, typeof(T)));
                }
            });
        }
eo_support
Posted: Tuesday, November 25, 2014 11:48:58 AM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,067
Yes. Except that you can use EvalScript directly instead of QueueScriptCall. QueueScriptCall is a little bit strange as it won't actually run the script without exiting the current message (which is how Dispatcher.Invoke is implemented). So you can actually create a deadlock there. We will probably revisit this method later to refine the internal mechanism of this method. For now it is recommended that you route the call to the UI thread and then use EvalScript.

Thanks!
Rasmus
Posted: Tuesday, November 25, 2014 12:18:23 PM
Rank: Advanced Member
Groups: Member

Joined: 4/17/2014
Posts: 35
eo_support wrote:
Yes. Except that you can use EvalScript directly instead of QueueScriptCall. QueueScriptCall is a little bit strange as it won't actually run the script without exiting the current message (which is how Dispatcher.Invoke is implemented). So you can actually create a deadlock there. We will probably revisit this method later to refine the internal mechanism of this method. For now it is recommended that you route the call to the UI thread and then use EvalScript.

Thanks!


Im using QueueScriptCall to be sure, that the js command executes asap. EvalScript might be called on wrong time and it will end with crash.
Any ideas how to handle that without creating waiting / blocking loop using CanEvalScript?
eo_support
Posted: Tuesday, December 2, 2014 10:32:04 AM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,067
Hi,

If you use QueueScriptCall, make sure you handle ScriptCallDone event. In the current implementation there can be problem if you immediately call WaitOne after QueueScriptCall. We have changed our code so that this will no longer be a problem in our next build.

Thanks!


You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.