加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 使用async / await和System.Threading.Tasks.Parallel时出

发布时间:2020-12-15 23:26:27 所属栏目:百科 来源:网络整理
导读:我有以下方法: public async Task ExecuteAsync(){ TaskIEnumerableComment gettingComments = RetrieveComments(); Dictionarystring,ReviewManager reviewers = ConfigurationFacade.Repositories.ToDictionary(name = name,name = new ReviewManager(nam
我有以下方法:

public async Task ExecuteAsync()
{
     Task<IEnumerable<Comment>> gettingComments = RetrieveComments();

     Dictionary<string,ReviewManager> reviewers = ConfigurationFacade.Repositories.ToDictionary(name => name,name => new ReviewManager(name));

     IEnumerable<Comment> comments = await gettingComments;

     Parallel.ForEach(reviewers,(reviewer) => {
          Dictionary<Comment,RevisionResult> reviews = reviewer.Value.Review(comments);

          int amountModerated = ModerateComments(reviews.Where(r => r.Value.IsInsult),"hide");
     });
}

我的ModerateComments方法如下所示:

private Task<int> ModerateComments(IEnumerable<Comment> comments,string operation)
{
      return Task.Factory.StartNew(() =>
      {
          int moderationCount = 0;
          Parallel.ForEach(comments,async (comment) => 
          {
               bool moderated = await ModerateComment(comment,operation); //Problem here
               if(moderated)
                   moderationCount++;
          }
          return moderationCount;
      };
}

最后:

private async Task<bool> ModerateComment(Comment comment,string operation,string authenticationToken = null)
{
      if(comment == null) return false;

      if(String.IsNullOrWhiteSpace(authenticationToken))
             authenticationToken = CreateUserToken(TimeSpan.FromMinutes(1));

      string moderationEndpoint = ConfigurationFacade.ModerationEndpoint;

      using(HttpRequestMessage request = new HttpRequestMessage())
      {
          request.Method = HttpMethod.Post;
          request.RequestUri = new Uri(moderationEndpoint);
          using(HttpResponseMessage response = await _httpClient.SendAsync(request)) //Problem here
          {
               if(!response.IsSuccessStatusCode)
               {
                    if(response.StatusCode == HttpStatusCode.Unauthorized)
                        return await ModerateComment(comment,operation,null); //Retry operation with a new access token
                    else if(response.StatusCode == HttpStatusCode.GatewayTimeout)
                        return await ModerateComment(comment,authenticationToken); //Retry operation

                    return false;
               } 
          }
      }

      return true;
}

我在运行时遇到了一个奇怪的问题.以上所有代码都正常工作,除非它到达该行:

using(HttpResponseMessage response = await _httpClient.SendAsync(request)) {
      //...
}

当我调试我的应用程序时,执行该指令,但就在此之后,它不会抛出任何异常,也不会返回任何内容,它只是完成执行并且我被派生到Parallel.ForEach循环的下一个语句.

这很难解释所以我会发布一些图片:

到目前为止一切顺利,我到达以下代码行:

执行进展顺利,我接到了对Moderation API的调用

即使我在调试器中按F10(Next语句),执行流也会跳转到Parallel.ForEach循环中的下一个循环.

正如你所看到的,我在try-catch中有断点,只是抛出任何异常,但断点永远不会被激活,也不会激活if(moderacion)commentCount中的断点.

那么这里发生了什么?我的执行流程去了哪里?它只是在将POST请求发送到API后消失了.

继续执行后,可枚举中的所有元素都执行相同的跳转,因此,我的commentCount变量最终等于0

解决方法

对常见问题的出色描述. Parallel.ForEach不支持异步lambda.异步方法一旦到达需要阻塞的第一个await就返回.发出HTTP请求时会发生这种情况.

对并行异步foreach循环使用一种常见模式.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读