4

我正在使用webBrowser.Document.InvokeScript("Function")运行 javascript,位于使用 Winforms WebBrowser 打开的本地文件中。

问题是,我需要 javascript 在继续之前完成执行。我该如何等待/聆听?

这是我的 C# 代码:

    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代码:

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

如何确保在 Script_B 完成之前未执行 Method_A?

4

2 回答 2

8

使用 async/await 您可以等到脚本执行而不会阻塞 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;
    }
}
于 2013-05-22T12:22:28.107 回答
0

您将需要实现一个回调方法(不要忘记ComVisible-Attribute),您将从脚本中调用该方法

window.mymethod();

这样,您实际上需要“拆分”您的方法。

是来自 SO 的一篇不错的帖子。


这是一个教程

从 Web 浏览器中托管的 JavaScript 调用 C# 方法

通过 AspDotNetDev,2011 年 5 月 6 日

此示例演示如何从 JavaScript 调用 C#。它还表明可以将参数传递给 C# 方法。

首先,创建一个 Windows 窗体应用程序。然后,将 WebBrowser 控件添加到您的窗体。然后修改表单的代码,使其看起来像这样:

 namespace WindowsFormsApplication6
{
    // This first namespace is required for the ComVisible attribute used on the ScriptManager class.
    using System.Runtime.InteropServices;
    using System.Windows.Forms;

    // This is your form.
    public partial class Form1 : Form
    {
        // This nested class must be ComVisible for the JavaScript to be able to call it.
        [ComVisible(true)]
        public class ScriptManager
        {
            // Variable to store the form of type Form1.
            private Form1 mForm;

            // Constructor.
            public ScriptManager(Form1 form)
            {
                // Save the form so it can be referenced later.
                mForm = form;
            }

            // This method can be called from JavaScript.
            public void MethodToCallFromScript()
            {
                // Call a method on the form.
                mForm.DoSomething();
            }

            // This method can also be called from JavaScript.
            public void AnotherMethod(string message)
            {
                MessageBox.Show(message);
            }
        }

        // This method will be called by the other method (MethodToCallFromScript) that gets called by JavaScript.
        public void DoSomething()
        {
            // Indicate success.
            MessageBox.Show("It worked!");
        }

        // Constructor.
        public Form1()
        {
            // Boilerplate code.
            InitializeComponent();

            // Set the WebBrowser to use an instance of the ScriptManager to handle method calls to C#.
            webBrowser1.ObjectForScripting = new ScriptManager(this);

            // Create the webpage.
            webBrowser1.DocumentText = @"<html>
                <head>
                    <title>Test</title>
                </head>
                <body>
                <input type=""button"" value=""Go!"" onclick=""window.external.MethodToCallFromScript();"" />
                    <br />
                    <input type=""button"" value=""Go Again!"" onclick=""window.external.AnotherMethod('Hello');"" />
                </body>
                </html>";
        }
    }
}

请注意,您的应用程序可能是 WindowsFormsApplication6 以外的命名空间的一部分,但如果您明确遵循上述说明,其余代码应该可以工作。我创建了这个提示/技巧,因为有人问我一个问题,他们不理解我发送给他们的这个示例。通过修复我发现的两个错误、添加未提及的 using 语句以及大量注释代码,此提示/技巧使示例更易于理解。希望你们其他人也会发现这个有用。执照

于 2013-05-22T12:13:39.607 回答