4

A TPL inside async implementation: mixing of implementaion concepts makes the code complicated or even buggy. Finally Parallel.ForEach is blocking the current thread which isn't allowed in async programming. Also avoid blocking operations on Task e.g. .Wait() or .Result for not completed Task. But I suggest totally different approach. Consider the simplified ...


3

My try to simplify and prettify the method. Avoid using globals in async code, pass Token as argument. // optimized out async State Machine private Task UpdateLogsAsync(IProgress<string> status, CancellationToken token) => Task.Run(async () => { await foreach (var message in this.Server.GetLogMessages().WithCancellation(token)) { ...


3

Overall, the code is quite clean and easy to understand. You did a good job of subdividing the work into small and easily digestible submethods. I did notice a few other things though, which I'll list below. Tasks vs threads Right now, it seems you're using Task.WhenAll and Task.Run as an async wrapper to emulate different concurrent threads. That's not ...


3

There are several improvement areas. Let's review them one-by-one from bottom up: GetXYZ private static async Task GetXYZ(string parameter) { await Task.Run(() => { var svc = new WebApiService(); var msg1 = svc.GeXYZ(parameter); if (string.IsNullOrWhiteSpace(parameter)) return; Console.WriteLine($"XYZ {...


3

I think instead of creating an unknown amount of task using PLinq would make it simpler and have control over the number of task inflight/created something like var result = model.Materials .AsParallel() .WithDegreeOfParallelism(8) // whatever you want or leave it out .Select(material => _materials.Get(...


2

thanks to @aepot for helping me clean this up. Changes from original: Tasks now start immediately when being added to tasks list to bypass the need to start them. SemaphoreSlim is used over Parallel.ForEach to control MaxDegreeOfParallelism as to not not deadlock. tasks.Where(x=> !x.IsFaulted) is removed because its sort of a race-condition where a task ...


2

According to my understanding your piece of software can finish in one of the following states: Succeeded Failed Timed out You are not exposing the ability to cancel it on the top level. So, it is not cancelable. Your explicit cancellation mechanism is not needed because: If timeout occurs at the top level then this fact will be available for all async ...


2

Here's pure async example without any workarounds. private async Task ProcessReport(Report report, ConcurrentDictionary<int, string> reportDictionary) { var (reportPath, bindingOrder, reportParameters) = report; var exportedImage = await _exporter.Export(_reportServerUrl, reportPath, export, reportParameters); if (exportedImage == ...


2

I think the code would be more readable and easier to maintain if there was a method that handled the main calling of the other handlers. Unless there is a reason for provider to be a property I would make it a readonly field instead. public class Sender : ISender { private readonly MethodInfo handlerMethodInfo; private readonly IServiceProvider ...


1

Async method out-of-the-box is using multiple threads for continuations. (Everything after await is continuation). Exception of this rule if existing SynchronizationContext. Don't Task.Run asynchronous I/O-bound operation, do it only for synchronous CPU-bound one. Asynchronous programming, SynchrinizationContext & TaskScheduler. Mixing .ContinueWith and ...


1

I would suggest you use something like System.Threading.Tasks.Dataflow or System.Reactive from NuGet. Dataflow in particular is made to feed data through a pipeline. Consider passing the CancellationToken to the delegate. Always validate arguments Smaller more specializes methods can make the code easier to understand. Example: public static Task<...


1

Just a suggestion to consider as improvement. Abstract example: public static class TaskExtensions { public static Task InvokeAfterAsync(this Task task, double thresholdMilliseconds, Func<Task> callbackAsync, CancellationToken token = CancellationToken.None) => task.InvokeAfterAsync(TimeSpan.FromMilliseconds(thresholdMilliseconds), ...


Only top voted, non community-wiki answers of a minimum length are eligible