首页>Program>source

长期阅读,这里是首次张贴。

我的目标:在使用webBrowser类时能够利用异步/等待.由于webBrowser.Navigate(string url)是一个异步方法,在激发LoadComplete事件之前,您无法检查html文档。

到目前为止,这是我的(有效)代码:

public class AsyncWebBrowser
{
    protected WebBrowser m_WebBrowser;
    private ManualResetEvent m_MRE = new ManualResetEvent(false);
    public void SetBrowser(WebBrowser browser) {
        this.m_WebBrowser = browser;
        browser.LoadCompleted += new LoadCompletedEventHandler(WebBrowser_LoadCompleted);
    }
    public Task NavigateAsync(string url) {
        Navigate(url);
        return Task.Factory.StartNew((Action)(() => {
            m_MRE.WaitOne();
            m_MRE.Reset();
        }));
    }
    public void Navigate(string url) {
        m_WebBrowser.Navigate(new Uri(url));
    }
    void WebBrowser_LoadCompleted(object sender, NavigationEventArgs e) {
        m_MRE.Set();
    }
}

并且上一堂Class现在允许我使用以下内容:

public async void NavigateToGoogle() {
    await browser.NavigateAsync("www.google.com");
    //Do any necessary actions on google.com
}

但是,我想知道是否有更有效/适当的方式来处理此问题.具体来说,具有阻止ManualResetEvent的Task.Factory.CreateNew.谢谢您的投入!

最新回答
  • 13天前
    1 #

    首先,我认为这是学习异步/等待方式的绝佳练习。

    为了使NavigateAsync返回任务,您似乎在跳绳.但是不必等待就可以返回Task!包含等待状态的方法必须返回Task,但是可以等待状态的方法不需要返回Task.它所要做的就是返回可以调用GetAwaiter的某种类型.

    您可以考虑实现这样的小类型:

    public struct WebBrowserAwaiter<T>
    {
        public bool IsCompleted { get { ... } }
        public void OnCompleted(Action continuation) { ... }
        public T GetResult() { ... }
    }
    

    并让NavigateAsync返回某种类型,您可以在该类型上调用GetAwaiter来返回webBrowserAwaiter.可以创建自己的GetAwaiter方法,而无需构建一个Task。

    更一般地说,您可能需要考虑的事情是如果在第一个仍在导航时再次调用NavigateAsync会发生什么?

  • 13天前
    2 #

    您 可以使用 TaskCompletionSource<T> 创建任务并将其标记为稍后完成。

    对于非一般性任务,我看不到任何替代方案,但是作为 Task<T> 来自 Task ,您可以只使用 TaskCompletionSource<object> 并将结果设置为null。

  • 13天前
    3 #

    我今天在另一个关于stackoverflow的文章的帮助下创建了这个类,我想使用(Async / Await)在没有任何线程阻塞的情况下获得现成的webbrowser控件. / p>

    Dim bb = New wbBrowser
    Dim wb = Await bb.GetBrowserAsync("http://www.msn.com")
    

    这是Class程:

    Imports System.Threading
    Imports System.Threading.Tasks
    Public Class wbBrowser
        Implements IDisposable
        Dim m_wbBrowser As New WebBrowser
        Dim m_tcs As TaskCompletionSource(Of WebBrowser)
        Public Sub New()
            m_wbBrowser.ScrollBarsEnabled = False
            m_wbBrowser.ScriptErrorsSuppressed = False
            AddHandler m_wbBrowser.DocumentCompleted, Sub(s, args) m_tcs.SetResult(m_wbBrowser)
        End Sub
        Public Async Function GetBrowserAsync(ByVal URL As String) As Task(Of WebBrowser)
            m_wbBrowser.Navigate(URL)
            Return Await WhenDocumentCompleted(m_wbBrowser)
        End Function
        Private Function WhenDocumentCompleted(browser As WebBrowser) As Task(Of WebBrowser)
            m_tcs = New TaskCompletionSource(Of WebBrowser)
            Return m_tcs.Task
        End Function
        Private disposedValue As Boolean
        Protected Overridable Sub Dispose(disposing As Boolean)
            If Not Me.disposedValue Then
                If disposing Then
                    m_wbBrowser.Dispose()
                End If
            End If
            Me.disposedValue = True
        End Sub
        Public Sub Dispose() Implements IDisposable.Dispose
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub
    End Class
    

  • 13天前
    4 #

    我将Vaibhav的VB代码翻译为C#.这是一个了不起的解决方案,我不知道为什么您对此感到失望。

    public class YourClassThatIsUsingWebBrowser : IDisposable
    {
        private WebBrowser browser;
        private TaskCompletionSource<BrowserResult> tcs;
        public YourClassThatIsUsingWebBrowser()
        {
            this.browser.DocumentCompleted += AsyncBrowser_DocumentCompleted;
            this.browser.Document.Window.Error += (errorSender, errorEvent) =>
            {
                SetResult(BrowserResult.Exception, errorEvent.Description);
            };
            this.browser.PreviewKeyDown += Browser_PreviewKeyDown;
            this.browser.Navigating += Browser_Navigating;
        }
        private void Browser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            tcs = new TaskCompletionSource<BrowserResult>();
        }
        private void Browser_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                this.browser.Stop();
                SetResult(BrowserResult.Cancelled);
            }
        }
        private void AsyncBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            SetResult();
        }
    
        public async Task<BrowserResult> NavigateAsync(string urlString)
        {
            this.browser.Navigate(urlString);
            return await tcs.Task;
        }
        private void SetResult(BrowserResult result = BrowserResult.Succeed, string error = null)
        {
            if (tcs == null)
            {
                return;
            }
            switch (result)
            {
                case BrowserResult.Cancelled:
                    {
                        tcs.SetCanceled();
                        break;
                    }
                case BrowserResult.Exception:
                    {
                        tcs.SetException(new Exception(error));
                        break;
                    }
                case BrowserResult.Succeed:
                default:
                    {
                        tcs.SetResult(result);
                        break;
                    }
            }
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        bool disposed = false;
        protected void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    this.browser.Dispose();
                }
            }
            disposed = true;
        }
    }
    public enum BrowserResult
    {
        Succeed,
        Cancelled,
        Exception,
    }
    

  • c#:如何测试素数?
  • 高性能"包含" C#字符串列表中的搜索