Как правильно вызвать токен отмены в методе asyn c в C#? - PullRequest
0 голосов
/ 08 мая 2020

Здесь я должен отменить асинхронный c метод LoadStoryHtmlData () либо из OnStoryChange (), либо из обработчика событий OnStoryModelPropertyChanged (). но я вижу, когда cts.Cancel (); называется, мой отладчик не попадает в блок catch (OperationCanceledException). что заставляет меня думать, что я неправильно применял токен cts. не могли бы вы помочь исправить этот блок кода.

private void OnStoryChange()
        {
            _logger.Log("OnStoryChange: storyId:" + _storyModel.StoryId);
            if (cts != null)
            {
                cts.Cancel();
            }
            try
            {
                if (_webBrowser != null && _webBrowser.IsBrowserInitialized)
                {
                    isJsCalled = false;
                    _webBrowser.Stop();

                    //If textData and html data are empty, the story is first to load.
                    if (_storyModel.HtmlData == null)
                    {
                        string loadingTip = string.Format("<html><b>{0}</b><br/><br/><i>Loading...</i></html>", _storyModel.Headline);

                         LoadStoryHtmlData(loadingTip);
                    }
                    else
                    {
                         LoadStoryHtmlData(_storyModel.HtmlData);
                    }
                }
            }           
        }

 private void OnStoryModelPropertyChanged(object sender, PropertyChangedEventArgs args)
        {

            if (args.PropertyName.Equals("HtmlData", StringComparison.OrdinalIgnoreCase))
            {
                var storyModel = sender as IStoryModel;
                if (storyModel != null)
                {
                    _logger.Log("OnStoryModelPropertyChanged: storyId:" + storyModel.StoryId);
                    LoadStoryHtmlData(storyModel.HtmlData);
                }
            }       
        }
private async void LoadStoryHtmlData(string text)
        {
            cts = new CancellationTokenSource();

            _logger.Log(string.Format("LoadStoryHtmlData: starting."));
            var nonHtmlText = string.Empty;
            try
            {
                if (BodyIsUrl(text))
                {
                    nonHtmlText = string.Format("<html><b>{0}</b><br/><br/><i>{{Content cannot be loaded.Please click on the link in release body view}}</i></html>", _storyModel.Headline);

                    if (_webBrowser != null && _webBrowser.IsBrowserInitialized)
                    {
                        // bool response = Task.Run(() => IsValidUrl(text)).Result;
                        if (await IsValidUrl(text, cts.Token))
                        {
                            _webBrowser.Load(text.Trim());
                        }
                        else
                        {
                            _webBrowser.LoadHtml(nonHtmlText, "http://www.reuters.com/" + Guid.NewGuid().ToString());
                        }
                    }
                }
                else
                {
                    text = LoadHtmlText(text);
                }
                _logger.Log(string.Format("LoadStoryHtmlData: ending. StoryId:{0}", _storyModel == null ? "" : _storyModel.StoryId));
            }
            catch (OperationCanceledException)
            {
                _logger.Log(string.Format("Load Operation cancelled."));
            }
            catch (Exception ex)
            {
                _logger.Error(ex.ToString());
                _webBrowser.Load(text.Trim());
            }
            cts = null;
        }
 public async Task<bool> IsValidUrl(string siteURL,CancellationToken ct)
        {
            try
            {
                if (siteURL.IndexOf(".xls") > 1)
                {
                    return false;
                }
                else
                {
                    ServicePointManager.Expect100Continue = true;
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                    Task<string> httpClient = GetContentType(siteURL.Trim());
                    var contentType = await httpClient;
                    _logger.Info("The Content type of the URL: " + siteURL + " is " + contentType);

                    if (contentType.Contains(Utility.Excel) || contentType.Contains(Utility.MsWord) || contentType.Contains(Utility.OctetStream) || contentType.Contains(Utility.OfficeDocument))
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex.ToString() + " With " + siteURL.Trim());
                return true;
            }

        }

1 Ответ

1 голос
/ 08 мая 2020

Ваш CancellationToken нужно как-то наблюдать.

Похоже, что вы выполняете работу, связанную с вводом-выводом, поэтому правильный способ наблюдения CancellationToken - передать его кому-либо API-интерфейсы, которые вы вызываете для фактического ввода-вывода.

В настоящее время код передает его на IsValidUrl, который затем выполняет ввод-вывод без передачи CancellationToken. Вам нужно будет изменить код так, чтобы CancellationToken передавался полностью вниз. В этом случае вы должны передать его в GetContentType, а GetContentType должен передать его любому типу, выполняющему фактический ввод-вывод (например, HttpClient).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...