How to cancel Task await after a timeout period

后端 未结 3 395
情深已故
情深已故 2020-11-22 03:33

I am using this method to instantiate a web browser programmatically, navigate to a url and return a result when the document has completed.

How would I be able to s

3条回答
  •  灰色年华
    2020-11-22 04:20

    I'm trying to take benefit from Noseratio's solution as well as following advices from Stephen Cleary.

    Here is the code I updated to include in the code from Stephen the code from Noseratio regarding the AJAX tip.

    First part: the Task NavigateAsync advised by Stephen

    public static Task NavigateAsync(this WebBrowser @this, string url)
    {
      var tcs = new TaskCompletionSource();
      WebBrowserDocumentCompletedEventHandler subscription = null;
      subscription = (_, args) =>
      {
        @this.DocumentCompleted -= subscription;
        tcs.TrySetResult(args.Url.ToString());
      };
      @this.DocumentCompleted += subscription;
      @this.Navigate(url);
      return tcs.Task;
    }
    

    Second part: a new Task NavAjaxAsync to run the tip for AJAX (based on Noseratio's code)

    public static async Task NavAjaxAsync(this WebBrowser @this)
    {
      // get the root element
      var documentElement = @this.Document.GetElementsByTagName("html")[0];
    
      // poll the current HTML for changes asynchronosly
      var html = documentElement.OuterHtml;
    
      while (true)
      {
        // wait asynchronously
        await Task.Delay(POLL_DELAY);
    
        // continue polling if the WebBrowser is still busy
        if (webBrowser.IsBusy)
          continue;
    
        var htmlNow = documentElement.OuterHtml;
        if (html == htmlNow)
          break; // no changes detected, end the poll loop
    
        html = htmlNow;
      }
    
      return @this.Document.Url.ToString();
    }
    

    Third part: a new Task NavAndAjaxAsync to get the navigation and the AJAX

    public static async Task NavAndAjaxAsync(this WebBrowser @this, string url)
    {
      await @this.NavigateAsync(url);
      await @this.NavAjaxAsync();
    }
    

    Fourth and last part: the updated Task GetUrlAsync from Stephen with Noseratio's code for AJAX

    async Task GetUrlAsync(string url)
    {
      using (var wb = new WebBrowser())
      {
        var navigate = wb.NavAndAjaxAsync(url);
        var timeout = Task.Delay(TimeSpan.FromSeconds(5));
        var completed = await Task.WhenAny(navigate, timeout);
        if (completed == navigate)
          return await navigate;
        return null;
      }
    }
    

    I'd like to know if this is the right approach.

提交回复
热议问题