Hopefully only a few more videos with this weird webcam angle 😅
@erikjlee1 Жыл бұрын
I finally figured out that you really need to set a bool property in your viewmodel indicating that some process is being executed, and then you can bind 'isEnabled' on any UI element to that property to disable interactivity until the process finishes (remembering to reset the bool property afterwards).
@emccartney Жыл бұрын
I personally find that async/await makes the cancellation & error cases much harder to handle. With tasks, you can chain things to operate on the happy, cancellation and error paths. With async/await you must wrap everything in try/catches and handle all cases manually which, ultimately leads to more code which probably isn't quite as pretty as your demos here. It might be interesting to cover this in a bit more detail in response to the original comment's question. They asked about async DB queries - assuming you are querying a local SQLite DB would the query time (probably in the millisecond range) be quicker than all the required async/await machinery required to complete the same task? In that case you might have a responsive app but worse performance than just running the query and updating the UI right away?
@SixthDemon Жыл бұрын
Heres the thing. Running async short tasks is definitely more harmful for the performance, I dont think anyone will argue with that. However, if we look at db, you can't ever be sure how long the tasks will take, and due to this, async is recommended. Regarding the cancelation issue: it shouldnt be in your view model in the first place, so view model should really care what type of the exception is there. What i do, is usually handle the exception on a service layer instead
@Manyadav428 Жыл бұрын
Великолепная связка. Арбитраж казался раньше сложной темы, а после ваших видео я даже удивился, что теперь могу без запинок использовать стратегии. Ждем новых видео!
@DotNetDemon83 Жыл бұрын
Back in the WinForms days, I would always just use a BackgroundWorker object to handle the marshaling of data getting sent to the form to be painted. No need for async or Task. But then again, life was a lot simpler back then. Edit: to add, if the control was interactive (e.g., text box) or if it involved the data being worked on, I would simply disable the control until it was done. The BackgroundWorker wouldn’t lock up the UI message pump.
@curtmantle7486 Жыл бұрын
Back in the WinForms days we used Background Workers and threads which were more painful and error prone. The TPL and Async/Await improved things a lot.
@pging83285 ай бұрын
what is a "task" in the context of async / await? coz it returns a "Task"?
@ivandrofly Жыл бұрын
Ive learnt a lot from you thank you so much with quality tutorials. Also please keep the WPF tutorials coming
@wvvwwwvvw Жыл бұрын
5:09 But did they really work *in parallel*? What I've been now reading about async calls is that they start on a separate thread and then come back to the main thread to the so-called continuation. And if the next statement in the continuation is also an `await smthAsync()`, it will also start on another thread, making a Terminator2 style "I'LL BE BACK" return. Eg: ```var response = await client.GetAsync(URL); var content = await response.Content.ReadAsStringAsync();``` in here, response and content are not run in parallel. But for some reason, your examples do look like as if they are executed in parallel. WTH?! :D
@SingletonSean Жыл бұрын
Yep, good call out! In the video example, I wrapped these in Commands that I don't await, so they are essentially "fire and forget". The second one runs without waiting for the first one to finish. If you really want to run them in parallel, you can use something like "Task.WhenAll" to execute them together. That will also not block the UI of course 😄
@UnknownMoses Жыл бұрын
You can't just block the UI thread with nothing telling the user the application is busy or they will think it is crashed and many users might end task on it plus it is annoying and bad design. My rule of thumb is to use execute on the UI thread if there is no chance the user will notice an unresponsive UI. Else I use another thread or async await. When working with a UI code interacting with any objects created on the UI thread needs to be executed on the UI thread anyway.
@SingletonSean Жыл бұрын
That's fair! I think I follow a pretty similar rule of thumb. I agree, I think UX is a huge factor here.
@UnknownMoses Жыл бұрын
@@SingletonSean I love your channel because I am new to WFP and have learned so much. So thank you for that!!! I have been a full stack software developer for over 25 years. What I find the most difficult is balancing the load between updating the UI and processing data in the background. For example lets say you have 250 results from a database that where each record needs to be represented with user controls as cards in a WPF items control. Processing of the data needs to happen in chunks of records on the background thread then passed to the foreground UI thread. For me the most difficult is determining the optimal number of records to pass to the UI thread on each iteration so the data is processed as fast as possible while not causing the UI to hang while adding user controls. Typically speaking the dataset would only contain 50 records max but need to account for a large dataset the user might query for. So I typically use a variable chunk size based on total number of records. So like 50 and
@UnknownMoses Жыл бұрын
@@SingletonSeanThrough substantial testing I can tell you the WPF items control when databound to a observablecollection is more than twice as fast as a winforms FlowLayoutControl when the dataset contains more than 50 records.
@SingletonSean Жыл бұрын
Yes, that's such an underrated concept! Not too often since it usually takes a significant amount of data, but I'm in the same boat where I've seen UIs hang from trying to update some sort of list with hundreds of items all at once. Of course, pagination would fix this issue too.
@dev.viktor Жыл бұрын
That's awesome. A brand new look on a thing that is so common and day-to-day used!
@SingletonSean Жыл бұрын
Indeed, thanks Viktor!
@atal_7 Жыл бұрын
Hey Sean, could you also make a video on wpf RichTextBox binding. Just like you did for PassworBox. Im having trouble with its text property binding. I tried creating dependency property was not able to save the text or put a placeholder on it.
@kylerbriskey372 Жыл бұрын
Could you do a video on how to organize somewhat bigger projects in WPF?
@DanimoDev Жыл бұрын
I think for anything that takes a while, async is a must, especially if you are doing some get call on some Web API that takes a while. It also allows user to cancel the operation (as well as timeout) as it doesn't lock up UI (for instance a user is searching and wants to search for something else midway through, this is a fairly common use case). If you need to disable functionality, you can manage the state of the UI programmatically if you don't want certain commands/interactions rather than have it all locked up. IE have a discrete save feature, where editing commands are disabled while data is saving and then enabled once saved without freezing entire app and user can still use all other non state changing features (like navigation and viewports etc). Much better UX. Another use case is reducing the startup time for an application that loads lots of data from multiple sources that needs to be loaded prior to main UI. Due to the parallellism of async you can just await all with loading screen, and once done, show main UI. Much faster than loading synchronously (as demonstrated in your video). Having said all that, it depends on the app. If it only has a small amount of local data, then I wouldn't bother as it's not worth the effort. If it is external and larger data, then I would definitely use async.
@SingletonSean Жыл бұрын
Great additional points here, especially startup time and cancellation cases!
@ClanLosFriendsGamer Жыл бұрын
Thanks Sean, very well explained as always, would love to see more of this. Here is also a suggestion for another short video. In the long KZbinViewers video you use DTOs and Models. I think I understood roughly why you do that but not really. And except for one other video you don't use it any further - is there a reason?
@SingletonSean Жыл бұрын
Thanks, good video idea! It really depends on the complexity of the domain. For simple CRUD-like domains, I'll likely just use the same class as a Model and DTO. For more complex domains with rich domain objects, I'll usually use a separate Model class for capturing the complex domain logic, and the DTO class for mapping to the external data source. That's just a short summary though 😄 I'll dig into this in a video and show some concrete examples.
@wvvwwwvvw Жыл бұрын
Could you also cover the race condition and the need for a thread-safe singleton? ;) Thanks. PS: Finally get to see the voice behind the scenes :D
@SingletonSean Жыл бұрын
Indeed, I can look into this! I have seen this in the wild a few times, but never had a reason to implement one myself
@feitan8745 Жыл бұрын
i'm kinda drunk, but i still don't forget to leave a like, because your content is always good in some way. and i code and think better when i'm drunk tho'.
@SingletonSean Жыл бұрын
Hahaha thanks Feitan, hope you're having a good time!
@feitan8745 Жыл бұрын
@@SingletonSeanyeah, i was organizing my stuff, preparing for a new challenge which doesn't involve just .NET thus the need to keep training on .NET. Still, great content as always.
@TinooT Жыл бұрын
That's great
@darrennew8211 Жыл бұрын
FWIW, don't use async/await in Rust. It doesn't run unless you're waiting for them to complete.
@ElCerdoBlanco11 ай бұрын
Of course you can use async/await in Rust. That's why tokio is one of the most popular crates. Rust is no different than other languages - you have to pass the Future to an executor to run it. If you always block your main thread to wait for asynchronous functions immediately, you are programming synchronously. That's not how it works.
@darrennew821111 ай бұрын
@@ElCerdoBlanco Sorry. I meant "don't use it this way." Because it's not a simple way to fire off a new thread and then wait for it to complete. It's a different concept from C# async/await.
@ifstatementifstatement2704 Жыл бұрын
‘Cause
@EduardoBonfandini Жыл бұрын
It's okay in some cases, it's trash in most cases.