Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoke a script in WebBrowser, and wait for it to finish running (synchronized)

I am using webBrowser.Document.InvokeScript("Function") to run a javascript, located in a local file opened with the Winforms WebBrowser.

The problem is, I need the javascript to finish executing before continuing. How do I wait/listen for that?

This is my C# code:

    private void Button1_ItemClick_1(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
    {
        webBrowser.Document.InvokeScript("Script_A");
        Method_A();
        DialogResult = System.Windows.Forms.DialogResult.OK;
    }

Javascript code:

<script>function Script_A() { Script_B(); }</script>

How do I make sure that Method_A is not executed before Script_B has finished?

like image 406
Valentin Kold Gundersen Avatar asked Feb 16 '23 11:02

Valentin Kold Gundersen


1 Answers

using async/await you can wait until the script is executed without blocking the UI.

public async void AMethod()
{
    string script =
     @"<script>
        function Script_A() { 
            Script_B(); 
            window.external.Completed(); //call C#: CallbackObject's Completed method
        }
        function Script_B(){
            alert('in script');
        }
    </script>";

    TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();

    webBrowser1.ObjectForScripting = new CallbackObject(tcs);
    //Ensure DocumentText is loaded before invoking "InvokeScript",
    //by extension method "SetDocumentTextAsync" (below)
    await webBrowser1.SetDocumentTextAsync(script);
    webBrowser1.Document.InvokeScript("Script_A");

    await tcs.Task;

    MessageBox.Show("Script executed");
}


[ComVisible(true)]
public class CallbackObject
{
    TaskCompletionSource<bool> _tcs = null;

    public CallbackObject(TaskCompletionSource<bool> tcs)
    {
        _tcs = tcs;
    }
    public void Completed()
    {
        _tcs.TrySetResult(true);
    }
}

public static class BrowserExtensions
{
    public static Task SetDocumentTextAsync(this WebBrowser wb, string html)
    {
        TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
        WebBrowserDocumentCompletedEventHandler completedEvent = null;
        completedEvent = (sender, e) =>
        {
            wb.DocumentCompleted -= completedEvent;
            tcs.SetResult(null);
        };
        wb.DocumentCompleted += completedEvent;

        wb.ScriptErrorsSuppressed = true;
        wb.DocumentText = html;

        return tcs.Task;
    }
}
like image 193
I4V Avatar answered Feb 18 '23 23:02

I4V