G
G
glaucidium2016-10-10 19:13:34
C++ / C#
glaucidium, 2016-10-10 19:13:34

How to properly organize a task cycle?

How to start processing in a loop of asynchronous (await) methods, and when they (together with the await code below) complete, continue the program synchronously?
I'm assuming this is a platinum question, but I couldn't find an answer on Google.
More specifically, I'm trying to go through the list of sites with a get-request, and depending on the response, do something with the site further. And at the end of the cycle, continue the program synchronously.
Here is the starting code.

List<Tuple<string, string>> addresses; // uri и host
List<Task> workTasks = new List<Task>();

foreach (var address in addresses)
{
  workTasks.Add(ProcessingRequset_await(address));
  //workTasks.Add(ProcessingRequset_wait(address));	
}
Task.WaitAll(workTasks.ToArray());
Console.WriteLine("Задачи завершены");
Console.ReadKey();

Here is the first response. It's fast, but the task is considered complete when it reaches await . Therefore, at the end of the cycle, the processing of responses is still ongoing.
public static Task ProcessingRequset_await(Tuple<string, string> address)
        {
            Task result = new Task(async () =>
            {
                HttpWebResponseLink httpWebResponseLink = new HttpWebResponseLink();

                try
                {
                    HttpWebResponse response = (HttpWebResponse) await GetResponseAsync(address.Item1, address.Item2);
                    httpWebResponseLink.IsHttpWebResponseTaked = true;
                    httpWebResponseLink.httpWebResponseLink = response;
                }
                catch (Exception e)
                {
                    httpWebResponseLink.IsHttpWebResponseTaked = false;
                }
    	        // логгирование и обработка результатов запроса
            });
            result.Start();
            return result;
        }

If in this code we replace:
HttpWebResponse response = (HttpWebResponse) await GetResponseAsync(address.Item1, address.Item2);
on the
Task<WebResponse> taskResponse = GetResponseAsync(address.Item1, address.Item2);
taskResponse.Wait();
HttpWebResponse response = (HttpWebResponse)taskResponse.Result;

then judging by the logs, the tasks are launched, as it were, in a second, and are completed almost simultaneously, and the cycle time is longer. On the other hand, the cycle ends when the tasks are completed completely.
This function simply hides the generation of request tasks.
public static Task<WebResponse> GetResponseAsync(string uri, string host)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
            request.Method = "GET";
            request.ProtocolVersion = HttpVersion.Version11;
            request.Host = host;

            Task<WebResponse> requestTask = request.GetResponseAsync();
            return requestTask;
        }

Answer the question

In order to leave comments, you need to log in

2 answer(s)
G
glaucidium, 2016-10-12
@glaucidium

Found a solution.
As far as I understand from https://msdn.microsoft.com/en-us/library/mt674893.aspx , an async Task method that does not have a return but has an await automatically issues a Task.
In general, I rewrote that method like this, and everything worked as it should. The logs say that the tasks start almost at the same time, and end when the appropriate responses to the requests come in. And the unsubscribe "Tasks completed" occurs only after the completion of all tasks.

public static async Task ProcessingRequset(Tuple<string, string> address)
        {
                HttpWebResponseLink httpWebResponseLink = new HttpWebResponseLink();
                try
                {
                    HttpWebResponse response = (HttpWebResponse) await GetResponseAsync(address.Item1, address.Item2);
                    httpWebResponseLink.IsHttpWebResponseTaked = true;
                    httpWebResponseLink.httpWebResponseLink = response;
                }
                catch (Exception e)
                {
                    httpWebResponseLink.IsHttpWebResponseTaked = false;
                }
                // логгирование и обработка результатов запроса
        }

I will also add that I found an even simpler way to process a list with long-awaiting operations:
var tasks = list.Select(async x =>
{
    var y = await IOProcessing(x);
    var z = await IOProcessing(y);
    Console.WriteLine(z);
});
Task.WhenAll(tasks).Wait();
Console.WriteLine(«Tasks completed»);

T
tex0, 2016-10-11
@tex0

Task.WhenAll

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question