How to cancel Task await after a timeout period

后端 未结 3 396
情深已故
情深已故 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条回答
  •  梦毁少年i
    2020-11-22 04:17

    I suspect running a processing loop on another thread will not work out well, since WebBrowser is a UI component that hosts an ActiveX control.

    When you're writing TAP over EAP wrappers, I recommend using extension methods to keep the code clean:

    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;
    }
    

    Now your code can easily apply a timeout:

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

    which can be consumed as such:

    private async Task GetFinalUrlAsync(PortalMerchant portalMerchant)
    {
      SetBrowserFeatureControl();
      if (string.IsNullOrEmpty(portalMerchant.Url))
        return null;
      var result = await GetUrlAsync(portalMerchant.Url);
      if (!String.IsNullOrEmpty(result))
        return new Uri(result);
      throw new Exception("Parsing Failed");
    }
    

提交回复
热议问题