How to use PostAsync() Request in a Loop?

Basically I need send a POST for each object on a List<>.

This is the main function that sends the post

public async Task<string> Set(int pessoaId)
    {
        try
        {
            Pessoas pessoa = new PessoasBLL().SelectBy("PessoaID", pessoaId);
            List<Endereco> lstEndereco = new EnderecoBLL().SelectByEntidade(pessoaId);
            Person person = new Person();

            person = SerializePerson(person, pessoa, lstEndereco);


            string token = new IntegracaoBLL().Select().ToUpper();
            // Put the following code where you want to initialize the class
            // It can be the static constructor or a one-time initializer
            if (client.BaseAddress == null)
            {
                client.BaseAddress = new Uri(baseURL);
            }
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Authorization =
                new AuthenticationHeaderValue("Basic", token);

            var data = JsonConvert.SerializeObject(person);

            var request = new StringContent(JsonConvert.SerializeObject(person), Encoding.UTF8, "application/json");

            var postResponse = await client.PostAsync("person", request);

            if (postResponse.StatusCode == HttpStatusCode.Created || postResponse.StatusCode == HttpStatusCode.NotAcceptable)
            {
                new PessoasBLL().SetImportacao(pessoaId, true);
            }

            return null;
        }
        catch (Exception ex)
        {
            return null;
        }
    }

The function work as fine when not in a loop, like this for example:

private void btnTeste_Click(object sender, EventArgs e)
    {
        new IntegrationWebApi().Set(8).ConfigureAwait(true);             
    }

But I’m having trouble getting this ‘code’ to work in a loop, like this for example

private void btnTeste_Click(object sender, EventArgs e)
    {
        try
        {
            List<Pessoas> pessoas = new PessoasBLL().SelectAllIntegracao();
            foreach (Pessoas p in pessoas)
            {
                new IntegrationWebApi().Set(p.ID).ConfigureAwait(true);
            }
        }
        catch (Exception ex)
        {
            XtraMessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
            new Logger().LogEntry(ex);
        }
    }

Sorry for any grammatical errors, english is not my main leanguage

Answer

It’s a shot in the dark, but I’m guessing that you think it doesn’t work because your program is not responding until it finishes the job, which is a huge loop of requests. But actually it’s working, just not so efficient.

First of all, creating a POST request inside a for loop in a UI Thread doesn’t sound so efficient. In the case that pessoas list has lots of members, your loop will wait POST request to finish to proceed to next iteration. And since this foreach loop inside of a UI Event (btnTeste_Click), your UI will not be responding (basically freeze) until all of the POST requests finish.

What I recommend is, modifying your Set() function to accept a List as parameter instead of integer, so foreach loop will work inside of the async service instead of UI thread, which will lift the load on your UI thread.

So your new functions will look like this: (Please be aware that I didn’t bother renaming all the stuff. Read carefully and refactor it to fit your needs before pasting and executing this. Since you defined your variables in your local language, I am not capable of fully understanding of consequences, so this method might not work for you.)

private void btnTeste_Click(object sender, EventArgs e)
    {
        try
        {
            List<Pessoas> pessoas = new PessoasBLL().SelectAllIntegracao();
            new IntegrationWebApi().Set(pessoas).ConfigureAwait(true);
        }
        catch (Exception ex)
        {
            XtraMessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
            new Logger().LogEntry(ex);
        }

and your function will be like;

    public async Task<string> Set(List<Pessoa> pessoas)
    {
        try
        {
            foreach(var pessoa in pessoas)
        {
            Pessoas newPessoa = new PessoasBLL().SelectBy("PessoaID", pessoaId);
            List<Endereco> lstEndereco = new 
            EnderecoBLL().SelectByEntidade(pessoaId);
            Person person = new Person();

            person = SerializePerson(person, newPessoa, lstEndereco);


            string token = new IntegracaoBLL().Select().ToUpper();
            // Put the following code where you want to initialize the class
            // It can be the static constructor or a one-time initializer
            if (client.BaseAddress == null)
            {
                client.BaseAddress = new Uri(baseURL);
            }
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Authorization =
                new AuthenticationHeaderValue("Basic", token);

            var data = JsonConvert.SerializeObject(person);

            var request = new StringContent(JsonConvert.SerializeObject(person), Encoding.UTF8, "application/json");

            var postResponse = await client.PostAsync("person", request);

            if (postResponse.StatusCode == HttpStatusCode.Created || 
    postResponse.StatusCode == HttpStatusCode.NotAcceptable)
            {
                new PessoasBLL().SetImportacao(pessoaId, true);
            }
}

            return null;
        }
        catch (Exception ex)
        {
            return null;
        }
    }