Tuesday, 22 May 2018

Async example


Here's a clue. The parent method needs the async keyword, the methods that are running asynchronously (called from the parent) don't. Weird.


A method that runs a heap of methods asynchronously. This guy needs the async keyword in the method signature:


        public async Task<List<RunResult>> RunMonitors(List<IMonitor> monitors)
        {
            var results = new List<RunResult>();
            try
            {
                var tasks = new List<Task<RunResult>>();
                foreach (var monitor in monitors)
                {
                    _logger.Debug($"About to run monitor {monitor.Name()}");

                    var newTask = Task.Run(() => monitor.Run());

                    tasks.Add(newTask);
                }

                _logger.Debug($"About to wait for monitor to complete; started {tasks.Count} tasks");
                await Task.WhenAll(tasks);

                _logger.Debug($"Monitors have completed; going to collect results");
                foreach (var task in tasks)
                {
                    results.Add(task.Result);
                }
            } catch (Exception ex)
            {
                _logger.Error($"Error while running monitors: {ex}");
            }
            return results;
        }

This bit starts the tasks running:
                foreach (var monitor in monitors)
                {
                    _logger.Debug($"About to run monitor {monitor.Name()}");

                    var newTask = Task.Run(() => monitor.Run());

                    tasks.Add(newTask);
                }

This bit causes everything to wait until all the tasks have completed:
                await Task.WhenAll(tasks);

This bit gets the results from each of the tasks
                _logger.Debug($"Monitors have completed; going to collect results");
                foreach (var task in tasks)
                {
                    results.Add(task.Result);
                }



Example of monitor run method with return type of Task<[an object]>. This guy doesn't need the async keyword (even tho it is running asynchronously with all its buddies).

        public Task<RunResult> Run()
        {
            DateTime started = DateTime.Now;
            var result = new RunResult
            {
                MonitorType = _type,
                Name = _name,
                RequestedAt = started
            };
            try
            {
                HttpResponseMessage response = _client.GetAsync(_url).Result;

                string responseString = response.Content.ReadAsStringAsync().Result;
                result.RunStatus = response.IsSuccessStatusCode ? Lookups.StatusLookup.Success : Lookups.StatusLookup.Failure;
                result.Response = response.IsSuccessStatusCode ? null : responseString;
                _logger.Info($"WebSiteMonitor: {_name} got a IsSuccessStatusCode of {response.IsSuccessStatusCode} and response of: {result.Response}");

            } catch(Exception ex)
            {
                _logger.Error($"WebSiteMonitor: {_name} caused an exception of {ex}");
                result.RunStatus = Lookups.StatusLookup.Failure;
                result.Response = ex.Message;
            }
            result.CompletedAt = DateTime.Now;
            return Task.FromResult(result);
        }


Example of how the parent method is called (just normal):

                var monitors = monitorManager.GetMonitors(config);
                var results = engine.RunMonitors(monitors).Result; // this method has the async keyword
                monitorManager.SaveRunResults(results);

No comments:

Post a Comment