Posts

Showing posts with the label Async Await

Async Constructor Functions In TypeScript?

Answer : A constructor must return an instance of the class it 'constructs'. Therefore, it's not possible to return Promise<...> and await for it. You can: Make your public setup async . Do not call it from the constructor. Call it whenever you want to 'finalize' object construction. async function run() { let topic; debug("new TopicsModel"); try { topic = new TopicsModel(); await topic.setup(); } catch (err) { debug("err", err); } } Readiness design pattern Don't put the object in a promise, put a promise in the object. Readiness is a property of the object. So make it a property of the object. The awaitable initialise method described in the accepted answer has a serious limitation. Using await means only one block of code can wait on the action. This is fine for code with guaranteed linear execution but in multi-threaded or event driven code it's unte...

Await Task.WhenAll(tasks) Exception Handling, Log All Exceptions From The Tasks

Answer : You've fallen foul of lazy evaluation - the result of Select will create a new set of tasks each time you iterate over it. You can fix this just by calling ToList() : var tasks = _factory.CreateMessage(settings) .Select(msg => SendScans(msg)) .ToList(); That way the set of tasks that you're awaiting will be the same set of tasks checked with your foreach loop. Instead of iterating over all tasks, you can get the Exceptions (if any) from the Task.WhenAll -Task: var taskResult = Task.WhenAll(tasks); try { await taskResult; } catch (Exception e) { if (taskResult.IsCanceled) { // Cancellation is most likely due to a shared cancellation token. Handle as needed, possibly check if ((TaskCanceledException)e).CancellationToken == token etc. } else if (taskResult.IsFaulted) { // use taskResult.Exception which is an AggregateException - which you can iterate over (it's a tree...

Await Vs Task.Wait - Deadlock?

Answer : Wait and await - while similar conceptually - are actually completely different. Wait will synchronously block until the task completes. So the current thread is literally blocked waiting for the task to complete. As a general rule, you should use " async all the way down"; that is, don't block on async code. On my blog, I go into the details of how blocking in asynchronous code causes deadlock. await will asynchronously wait until the task completes. This means the current method is "paused" (its state is captured) and the method returns an incomplete task to its caller. Later, when the await expression completes, the remainder of the method is scheduled as a continuation. You also mentioned a "cooperative block", by which I assume you mean a task that you're Wait ing on may execute on the waiting thread. There are situations where this can happen, but it's an optimization. There are many situations where it can't...

Async Task.WhenAll With Timeout

Answer : You could combine the resulting Task with a Task.Delay() using Task.WhenAny() : await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(timeout)); If you want to harvest completed tasks in case of a timeout: var completedResults = tasks .Where(t => t.Status == TaskStatus.RanToCompletion) .Select(t => t.Result) .ToList(); I think a clearer, more robust option that also does exception handling right would be to use Task.WhenAny on each task together with a timeout task, go through all the completed tasks and filter out the timeout ones, and use await Task.WhenAll() instead of Task.Result to gather all the results. Here's a complete working solution: static async Task<TResult[]> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks, TimeSpan timeout) { var timeoutTask = Task.Delay(timeout).ContinueWith(_ => default(TResult)); var completedTasks = (await Task.WhenAll(tasks.Select(task => Task.WhenAny(task, ...