异步/等待中的foreach使用了HTTPClient [英] Async/Await in foreach with HTTPClient

查看:161
本文介绍了异步/等待中的foreach使用了HTTPClient的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个加载了一些插件(DLL)和调用他们的过程方法的web服务。之一的插件需要成员的列表,并确保它们都包含在一个MailChimp列表

下面是code,增加了用户的MailChimp组。

 专用异步任务AddMCUsers(列表<&成员GT; _memberList)
    {
        使用(VAR HTTP =新的HttpClient())
        {
            VAR creds = Convert.ToBase64String(Encoding.ASCII.GetBytes(用户名:密码);
            http.DefaultRequestHeaders.Authorization =新System.Net.Http.Headers.AuthenticationHeaderValue(基本,creds);
            字符串memberURI =的String.Format(@{0}清单/ {1} /成员,_baseURI,_memberGroupId);
            VAR JSS =新的JavaScriptSerializer();            的foreach(在_memberlist VAR用户)
            {
                变种_addStatus =;                尝试
                {
                    VAR内容= jss.Serialize(新MCPost()
                    {
                        EMAIL_ADDRESS = user.Email,
                        状态=订阅,
                        merge_fields =新MCMergeFields()
                        {
                            FNAME = user.Firstname,
                            LNAME = user.Lastname
                        }
                    });                    使用(VAR结果=等待http.PostAsync(memberURI,新的StringContent(内容,Encoding.UTF8,应用/ JSON)))
                    {
                        VAR resultText =等待result.Content.ReadAsStringAsync();                        如果(result.IsSuccessStatus code)
                        {
                            _addStatus =成功;
                            VAR _returnedUser = jss.Deserialize< MCMember>(resultText);
                            //存储新用户的ID
                            user.ServiceId = _returnedUser.id;
                        }
                        其他
                        {
                            _addStatus =失败;
                        }
                    }
                }
                抓{
                    _addStatus =错误;
                }                的LogEvent(添加用户 - + _addStatus,的String.Format(ID:{0} - {1} {2}(帐户:{3}){4},user.Id,user.Firstname,用户。姓氏,user.AccountId,user.Email));            }
        }
    }

在正常程序code,这不会是一个问题。然而,唯一可用的Post方法对HttpClient的是PostAsync。作为相当新的异步/等待的东西,我不知道我的code其余部分的后果......尤其是当它涉及到我的尝试重用HttpClient的,而不是实例为每个HTTP调用一个新的

我不知道用的await会发生什么时,其在foreach裹得像我有。我会重用HttpClient的异步运行时,进行多次呼吁遇到问题?

我的另一个问题是,什么是真正将要返回。 IOW,我的理解是,等待回报的任务。然而,在这里,我通过循环列表,使多个呼叫等待PostAsync。我的方法返回一个任务。但任务获取返回?如果我的调用方法需要在移动之前等待完成,什么是它的呼叫样子?

 私人无效处理()
{
    //获取列表    VAR任务= AddMCUsers(名单);
    task.Wait();    //后续处理
 }

我读过,你应该使用异步一路。这是否意味着我的调用方法应该看起来更像是这样?

 公共异步任务处理()
 {
    //获取列表
    ...
    等待AddMCUsers(名单);    //其他处理
  }

由于力所能及的帮助,你可以在此提供的。


解决方案

  

在正常程序code,这不会是一个问题。


整点异步 / 等待是写异步code,看起来几乎办法等同于正常同步code。


  

作为相当新的异步/等待的东西,我不知道我的code其余部分的后果......尤其是当它涉及到我的尝试重用HttpClient的,而不是用于实例化一个新的每个HTTP调用。


的HttpClient 是为了重复使用;事实上,它可以用于任何数量的同时通话。


  

我不知道用的await会发生什么时,其在foreach裹得像我。


想起来的一种方法是,等待暂停的方法直到操作完成。当操作完成,则该方法继续执行。我有一个 异步介绍了进入更多的细节。


  

我会遇到的问题与重用HttpClient的异步运行时,进行重复调用?


没有,这很好。


  

IOW,我的理解是,等待回报的任务。


的await 需要的一个工作。它解开这一任务并返回任务的结果(如果有的话)。如果任务有一个例外完成,那么<​​code>的await 引发的异常。


  

我的方法返回一个任务。但得到返回哪个任务?


工作异步是由异步状态机。你不必为此担心。见我介绍更多的细节。


  

如果我调用方法需要在移动之前等待完成,什么是它的呼叫样子? ......我读过,你应该异步一路使用。这是否意味着我的调用方法应该看起来更像是这样?


是的,它应该看起来像你的第二个片段:

 公共异步任务ProcessAsync()
{
  //获取列表
  ...
  等待AddMCUsers(名单);  //其他处理
}

我唯一改变的是异步后缀,这是由的基于任务的异步模式

I have a webservice that loads up some plugins (dlls) and calls their Process method. One of the plugins takes a list of members and ensures that they are all included in a MailChimp list.

Here is the code that adds the users to the MailChimp group.

    private async Task AddMCUsers(List<Member> _memberList)
    {
        using (var http = new HttpClient())
        {
            var creds = Convert.ToBase64String(Encoding.ASCII.GetBytes("user:password");
            http.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", creds);
            string memberURI = string.Format(@"{0}lists/{1}/members", _baseURI, _memberGroupId);
            var jss = new JavaScriptSerializer();

            foreach (var user in _memberlist)
            {
                var _addStatus = "";

                try
                {
                    var content = jss.Serialize(new MCPost()
                    {
                        email_address = user.Email,
                        status = "subscribed",
                        merge_fields = new MCMergeFields()
                        {
                            FNAME = user.Firstname,
                            LNAME = user.Lastname
                        }
                    });

                    using(var result = await http.PostAsync(memberURI, new StringContent(content,Encoding.UTF8, "application/json")))
                    {
                        var resultText = await result.Content.ReadAsStringAsync();

                        if(result.IsSuccessStatusCode)
                        {
                            _addStatus = "Success";
                            var _returnedUser = jss.Deserialize<MCMember>(resultText);
                            //Store new user's id
                            user.ServiceId = _returnedUser.id;
                        }
                        else
                        {
                            _addStatus = "Fail";
                        }
                    }
                }
                catch {
                    _addStatus = "Error";
                }

                LogEvent("Add User - " + _addStatus, string.Format("Id: {0} - {1} {2} (Account: {3}) : {4}", user.Id, user.Firstname, user.Lastname, user.AccountId, user.Email));

            }
        }
    }

In normal procedural code, this wouldn't be a problem. However, the only Post method available on the httpClient was PostAsync. Being fairly new to the async/await stuff, I'm not sure the ramifications on the rest of my code ... particularly as it relates to my attempt to reuse the httpClient instead of instantiating a new one for each http call.

I'm not sure what happens with await when its wrapped in a foreach like I have. Will I run into issues with reusing the httpClient to make repeated calls when running asynchronously?

My other question is, what is actually going to be returned. IOW, my understanding is that await returns a Task. However, here, I'm looping through the list and making multiple calls to await PostAsync. My method returns a Task. But which task gets returned? If my calling method needs to wait for completion before moving on, what does its call look like?

private void Process()
{
    //Get List

    var task = AddMCUsers(list);
    task.Wait();

    //Subsequent processing
 }

I've read that you should use Async all the way. Does this mean my calling method should look more like this?

 public async Task Process()
 {
    //Get list
    ...
    await AddMCUsers(list);

    //Other processing
  }

Thanks to whatever help you can offer on this.

解决方案

In normal procedural code, this wouldn't be a problem.

The whole point of async/await is to write asynchronous code in a way that looks practically identical to "normal" synchronous code.

Being fairly new to the async/await stuff, I'm not sure the ramifications on the rest of my code ... particularly as it relates to my attempt to reuse the httpClient instead of instantiating a new one for each http call.

HttpClient was intended to be reused; in fact, it can be used for any number of calls simultaneously.

I'm not sure what happens with await when its wrapped in a foreach like I have.

One way to think of it is that await "pauses" the method until its operation completes. When the operation completes, then the method continues executing. I have an async intro that goes into more detail.

Will I run into issues with reusing the httpClient to make repeated calls when running asynchronously?

No, that's fine.

IOW, my understanding is that await returns a Task.

await takes a Task. It "unwraps" that task and returns the result of the task (if any). If the task completed with an exception, then await raises that exception.

My method returns a Task. But which task gets returned?

The Task returned from an async method is created by the async state machine. You don't have to worry about it. See my intro for more details.

If my calling method needs to wait for completion before moving on, what does its call look like? ... I've read that you should use Async all the way. Does this mean my calling method should look more like this?

Yes, it should look like your second snippet:

public async Task ProcessAsync()
{
  //Get list
  ...
  await AddMCUsers(list);

  //Other processing
}

The only thing I changed was the Async suffix, which is recommended by the Task-based Asynchronous Pattern.

这篇关于异步/等待中的foreach使用了HTTPClient的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆