How to Report Progress with Async/Await in .NET Core 3
HTML-код
- Опубликовано: 19 окт 2024
- In this video, we learn how to report progress with async/await in .NET Core 3. If you're using async await, chances are you have long running processes executing on different threads. However, it's very common to update the user on the current progress of that operation in the UI. Maybe you are downloading or uploading files to a server. Perhaps you are copying a number of files from one location to another. Whatever your reason, reporting the progress of an async await process is very easy.
Start by having your method doing the work report the progress using the IProgress(OfT) interface. This interface allows you to report the progress of your method when using async await. It may look something like this:
void LoopThroughNumbers(int count, IProgress(ofInt) progress)
{
for (int x = 0; x (lessthan) count; x++)
{
Thread.Sleep(100);
var percentageComplete = (x * 100) / count;
progress.Report(percentageComplete);
}
}
Now that your method is reporting the progress of its operation, you can now respond to that progress report and display it to the user. Start by creating a new Progress(ofT) object and provide your handler as follows:
var progress = new Progress(ofInt)((value) =(greaterThanBracket)
{
_progressBar.Value = value;
_textBlock.Text = $"{value}%";
});
Once your progress handler is in place, you can now pass this to your method being run in a task to report the progress of your async await method.
await Task.Run(() =(greaterThanBracket) LoopThroughNumbers(100, progress));
That's it!!! You're all done.
Bonus Tip: Don't use Task.Run in the implementation of a method; instead, use Task.Run to call the method.
Check out my new Pluralsight course "Introduction to Prism for WPF":
pluralsight.px...
Sponsor Me:
github.com/spo...
Follow Me:
Twitter: / brianlagunas
Twitch: / brianlagunas
Blog: brianlagunas.com
GitHub: github.com/bri...
It me four hours to find this superb 7 min solution. Thank you, Brian.
Thank you so much for watching
why you are soo good at teaching ? dayuuum
i swear i'm not just complimenting you , your teaching method is clear and straight to the point
which is something we often miss IRL in schools, and also online .
Thank you so much for the kind words. I appreciate you
Exactly answered my question, and in only 7 minutes. Clear, concise, and simple. I wish all example videos were this clear. Thank you * 1000!
Thank you for the kind words
This is such a nice explanation and relatively easy to follow! Thanks for your contribution to the community
Thank you so much for the kind words
Thank you, this is the most simplistic way of showing progress that i found so far. Please make more videos like this they are awesome!
Thank you so much for the kind words. I want to make more videos, I just haven’t had time. My day job is very demanding.
Wow, super video. This concept was on a coding interview home exercise and I didn't know how to report. THANK YUUUUU
You’re very welcome
Just found this today - what a simple to follow and very helpful tutorial - just implemented the principles in a piece of code and it worked. Thank you!
Awesome! Great to hear! Thanks for watching
such a complicated concept taught so easily, wow, appreciate it
Great as always. The next episode could be about the cancelationToken. The user start a task but before finish he decides to cancel that task.
That's a good idea! Thanks for sharing
Amazing. Simple solution and with the aync await, it cleared up my window studder. Thanks!
Great to hear! Thanks for watching
Greatest example ever. Extremely clear. Let me bow my head for you 3 times. Thank you very much.
Thank you so much for the kind words. Thank you for watching
Again, everything is very simple.
And as you know, everything simple is brilliant!
Thanks Brian!
Thank you very much
you have a new subscriber, by the way let me tell you that you do a great job explaining net.core easy and straight to the content
Fantastic video again Brian. This couldn't have come at a better time as I'm attempting this exact thing at work now to improve user experience :)
Also great Key point about Task.Run(). I have the habit of putting a Task.Run in the method implementation. Therefore, thanks for the heads up on that one! :D
Thank you very much for watching.
Is there something special about Progress that that allows it to update the controls on the UI thread or will any lambda function created on the UI thread hold the thread it was created on in it's closure?
Great explanation, very useful 👍Thanks
Thank you for watching
Thanks Brian, you got the best content right now. You are the best
Thank you very much for the kind words.
Excellent content. Short and sweet! Thanks a lot.
Thanks for watching
Very clear explanation !! Loved it👌
Thank you very much sir
Thank for this video, its very simple but usefull for work !! )
Thanks for watching
Maybe it's just me but I've noticed in your latest videos that the audio/video are not in sync.
Great video btw. Thank you.
Yeah, this is a known issue with RUclips. It works fine on some browsers/devices, and the audio is out of sync on other devices/browsers. I've seen this on my Android while it works perfectly on my Desktop. I am not sure how to prevent that from happening.
@@BrianLagunas but with your youtube video from twitch it doesn't happen.
Yeah, its very weird. I tried some different settings on my next video which will be released tomorrow. Hopefully these new setting will fix the problem. Let me know
So simple to understand now
So glad to hear.
perfect answer to my question!
Great to hear!
Wow! Best explanation I've seen. Thanks a lot
Thank you very much
Thank you so much, this is very useful and easy to understand.
Thank you for watching
Great Brian!! Waiting for more ...
More videos are coming :)
I can't thank you enough for this great video
Thank you so much for watching
As usual, awesome explanation :)
Thank you sir
Hi Brian, this is the best video i have seen about this subject, Thank you. i have one question though. if i choose let's say count = 5,
the progress will not go till the end of the bar which i assume is not what we want. No matter the count we should get 100%. Any idea?
The math in that demo already handles that scenario. The only thing you'll need to do is set the final 100% state when the task has completed since the progress will not be reported on task completion.
@@BrianLagunas Thanks for the quick reply. I will see how i can manage that. I'm kinda new to this.
Brilliant, thanks Brian 👍🏻
Thank you very much.
you saved my day !!! super
Great to hear! Thanks for watching
So my question is: how can I become as cool as Brian Lagunas? :)
HAHAHA!!! You're way cooler than me.😀
awesome, thats what I needed.
Great to hear
Thank u for your videos. I have a question. Usually if we work with a threads then you can set any Control only from UI thread. Here u used Progress class which are invoked through a SynchronizationContext instance captured when the instance is constructed and in your example this is UI thread. So in case if we were using different class, it won't work. Am i right?
Great video Brian!
Thank you so much Jesus
Awesome video Brian, thank you so much for this !!
Just one tip about your rule: "Do not use Task.Run in the implementation of the method...": Some situations, like using a nuget package that performs async operations or creating a custom nuget package to use accross many projects, is required return tasks objects and the consumer project use the "await" keyword.
One additional question is: How can I report progress when execute a external .exe or any command line, using Process class ? In this case, I don't have a loop or anything like this, you know? The command line can perform a looong time to complete. I can estimate a duration of the command, but I don't know how update the progress bar while the time is passing. I think that is something like a "tick" check in a async task
In order to show a meaningful progress bar, you need an end goal... how long should it take. If the exe you're executing doesn't give you a way to know that you have no way of calculating a percent cause there's nothing to compare current progress to. You're stuck with exactly what you are doing... an estimation based on what you normally see it take. For this reason, you either have to make up an end goal or don't bother with a progress bar cause it'll probably be meaningless to the user.
In other words, if the external process doesn't report progress, you are limited in what you can report. It's a black box.
Thank you so much.
Thanks for watching
Thanks, I used similar in .net framework
Great 👍
Is it me or the last few videos have an audio delay?
Good explanation by the way. Great video.
Yes, some people have seen an audio delay, but I am unable to. It's really weird and frustrating on my part. I am trying to figure out what could be causing the issue. It's the never ending "it works on my machine" LOL
Brian, please can you clarify whether this approach (passing IProgress) of updating progress bar is specifically when we use async/await with Task.Run? Where as if I had used async/await without Task.Run (say for couple of io bound operations in a for loop) then I could directly update the progress bar value (because it's all happening on the same thread)?
Correct. If you have a task method that reports progress, using calling Task.Run isn't required.
Great video
thank you for watching
I've always used BackgroundWorker and Report progress event. Is the behavior different?
Background worker is the "old way" of doing background tasks and reporting progress (which still works). If you're using the newer async/await approach, then this is how you would do it.
I have similar code in my WPF apps but was wondering if the method LoopTheoughNumbers() was doing an IO bound async task, would it still be “best practice” to call it with the Run.Task() ?
Tkx again Brian
You want to use Task.Run to call CPU-bound methods only
Hi Brian, I've always wanted to do this. Thanks! I'm just wondering though, at the end, when you did your victory dance by grabbing the title bar and dragging it all over you screen, what were you actually demonstrating by doing that? I already believed the the windows async manager works properly. :). Maybe if you pressed a cancel button, then I would have been impressed. Wait, was there a cancel button?
I was demonstrating that the UI is not being locked up or blocked by the reporting of the progress that is being reported from the long running task. The UI is remaining responsive during the entire process of running the task and updating the UI with the reported progress. There was not a cancel button. Maybe I should add one :)
If my code looks like this how would I report progress?
using (HttpRequestMessage request = new HttpRequestMessage(method, uri) {
HttpClient client = new HttpClient();
Task task = client.SendAsync(request);
HttpResponseMessage response = await task;
I’ve noticed that when defined like this I don’t have access to task.Run()
I see task.RunAsynchronousily though
I’ve been trying to adapt several progress reporting methods but I haven’t been able to get any of them to work.
Great!
Thank you so much
Brian, can you please tech us how to copy a lot files with sub directories without blocking the UI? Thanks in advance
That might make for a good video 😀
@@BrianLagunas that would be awesome 😁
@@julianturner6203 Here you go ruclips.net/video/8PLlHDfN-ew/видео.html
I need an explanation on why it is inefficient? Please explain the "Do not run the task.run in the implementation oof the [async] method"???
I have a problem; the progressbar only updates at the end of the method.
It is worth to mention that the method im trying to run async is located in a seperate cs file.
tried moving the method to the xaml.cs file where the caller is located ,still not working
nevermind, was my own stupidity, i forgot to put thread sleep, apparently it goes too fast to update :D
Awesome! I am glad you figured it out.
I had that problem with the Textbox. Then I just called .Update at the Textbox right after the change to the .Text Property.
Hi Brian,
Can you please do a video on creating a user control with dependency property, routed event and to implement commanding with a user control.
How to attach a command to handle click event with a user control.
Thanks
Rahul Mathew
That's a lot for one video. These would have to be broken down into separate videos. Also, it sounds like you should probably be using a Custom Control not a UserControl.
@@BrianLagunas Hi Brian, I am watching your plural sight. So in that, the course title is given Custom Control. So should I follow that one. Is there is a difference between custom and user control?
Please advise
Thanks
Rahul Mathew
@@rahulmathew8713 Yes there is a difference. I believe I talk about those differences in the course. Thanks for watching :)
Hi. i am loving your videos . Big fan . I have a question regarding "DialogAware". How do i know if a dialog i already open? I don't want to open a dialog 2 times . There is way to ask the dialog service?
Thank you
Thank you for watching. It sounds like you'll need to create a custom dialog service that derives from the Prism service, and add the ability to track your dialog instances.
How would you do same thing when it is . Net core mbc application and you are uploading large excel file and this file is being processed on separate class library project called from mvc controller? Show progress bar in real time?
Since it doesn’t sound like your upload method supports reporting progress, you’ll just show an indeterminate progress bar when you start the upload and close it when the upload completes.
@@BrianLagunas Thanks for confirmation
Hi, thanks for your Video. How I can do that with DI Containers?
I'm sorry, but I don't understand the question. Do what exactly with a DI container? Can you provide more detail?
@@BrianLagunas Thanks for your answer. I mean Dependency Injection Containers like Autofac, Ninject etc... How can i access the Progress Class on the calling class when autofac is automatically injecting the Progress Class? Sorry 4 my bad english...
Usually you'll register your service class with the container and then the container would automatically inject that service class into the ctor of the class your trying to use it in. Also, don't worry about your English. Its great! I envy anyone that can speak multiple languages.
@@BrianLagunas Hello thank you, do you think a video about this would be helpful for many of your followers? I am currently trying to get closer to the solid principles
I could probably do a video series on the SOLID design principles. Great idea!
How to debug Task and threads in better way in c#?
Great qustion!
Hm but whats wrong with wrapping implementation of method with task.run, i did it a lot and just like await MyMethod() and i am happy with that, why its better to wrap synchronous method within task.run?
Here's a great blog post by Stephen Cleary that explains the issue with Task.Run in the method implementation very well: blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html
@@BrianLagunas thanks, great post!
@@BrianLagunas Maybe that whole story is worth a video in itself. Steven refers to ASP.net most of the time, so I focussed example might be worth it. At least for me I just got rid of a sexy busy indicator which is replaced by data just being there synchronosly, bamm!
So my question would be, if there is some sort of natural tipping point, where you suggest to go async because it is too slow or is it pure try and error when you switch over?
@@janhendrikschreier I always place the loading of data on a worker thread in my desktop apps. My #1 rule is to keep the UI responsive at all times. Considering the various numbers of unknowns of the end-user system (RAM, processor, cache size, etc), I don't take a chance.
Feels like events are used less and less now.
Technology keeps making things easier for us.
does this work on ASP.NET?
There may be some differences, but in general it should work.
Unhandled Exception: explicit use of "pretty cool right?" belongs to StyroPyro lol
I’m guessing that’s another RUclipsr that says that a lot? 🤣
@@BrianLagunas Yes, it's his main catch phrase, but I wasn't being serious at all, just trying to crack a joke in the comments. I appreciate your work man, and your video have been very helpful to me.
but how to update progress from a specific task like API resquests/ long running task ???
If the API doesn’t provide a way to report progress you’ll have to use a non-deterministic progress indicator.