First time seeing someone explaining ConfigureAwait(false) properly in an easy-to-understand manner. Thank you!
@DerXavia10 ай бұрын
Indeed, I actually hated the description in the official documentation, its written like they specifically do not want you to understand it.
@weicco10 ай бұрын
I have a feeling that if people would, instead of diving directly into .NET async and threading, take a bit time to learn how threading works below the hood, below the virtual machine, at the operating system level. I found it really helpful when I spent a few weeks tinkering around with Win32 interface back in 2000. I read about threading and how the "async" methods we had back then worked. Then I tested them myself with few simple lines of code. I finally got so excited that I went and read how threading and process model is implemented in different operating systems, and even helped a friend of mine to implement prioritized task list on his own operating system. You won't have to go that far but maybe spend a day with just reading and testing things. I find that reading is not enough. You need to test it to get "the feeling" of it even if the code is ridiculously small like three lines. But this way you'll learn not just the thing but how to apply the thing to different problems and situations. Just my two cents.
@serus164 Жыл бұрын
The laugh kills me every time
@pmro Жыл бұрын
First and second time I'm watching for knowledge but my 3rd time will be for that laugh 😅
@andrewkaplanovsky57111 ай бұрын
Yup, the presenter is slightly hysterical
@Vladimir-ro7jw7 ай бұрын
More like frightening than entertaining
@tiosatria99193 ай бұрын
me too hahahaha
@LasseVågsætherKarlsen10 ай бұрын
Slightly misleading that the first slide mentions Thread 2, when in fact there is absolutely no guarantee that another thread will be created. Additionally, "Thread 1", executing at that point, will still call into the DownloadDataAsync method, and only at the point when some code, which could be severall call layers deeper, actually ends up creating and returning a not-yet-completed-task, then it returns back. And we're still on thread 1, no thread 2, and if the task is actually related to async I/O, a new thread might still not have been created. At some point, when that yet-to-be-completed task actually completes, at that point some new thread might be created (or a threadpool task created), or the main thread might pick it back up, which means even here we do not guarantee that we have multiple threads. So it is misleading to start off a talk about async/await to say that we get additional threads, at least when the whole video does such a wonderful deepdive on everything else. There are so many people going around believing that async/await creates threads all willy nilly, so it's misleading that this video seems to continue that misrepresentation.
@withkittens253210 ай бұрын
I too was... surprised by the first slides, I stopped watching at that point. Does the talk get better after that?
@elliotdematteis78255 ай бұрын
Exactly, the first slide implies that you can't use async/await with 1 thread, which is totally untrue. await just queues a user work item on the threadpool, it's totally possible for same thread that queued the work to get the work.
@robertschmidt-cisternas80545 ай бұрын
This is completely correct. It's amazing to me that he has not corrected these statements after all these years of doing the same talk. It's actually infuriating that he, with the authority and confidence of a LLM, propagates factually false information to people who are trying to understand and learn a difficult topic.
@handlez41111 ай бұрын
🎯 Key Takeaways for quick navigation: 00:07 🚀 *Overview of the Talk* - Session introduces correcting common mistakes in async and await. - Speaker highlights the growth of the talk since its first presentation in 2018. - Mention of additional resources available for reference. 01:34 🧠 *Understanding Async/Await* - Examining an example method "ReadDataFromURL" with async task. - Explanation of how the async/await mechanism allows for non-blocking execution. - Emphasis on freeing up the main/UI thread during asynchronous operations. 03:55 🔄 *Dive into Compiler-Generated Code* - Insight into the compiler-generated code for async methods. - Discussion on the transformation of async methods into a private sealed class. - Explanation of fields, move next method, and handling exceptions within the generated code. 06:23 📉 *Impact on App Size and Compile Time* - Briefly addresses the negligible impact of async on app size and compile time. - Mention of the generated class and fields contributing to a slight increase in app size. - Contextualizes the impact, highlighting its minimal significance for most projects. 07:30 🕵️ *Async Void and the "move next" State Machine* - Introduction to the challenges of using async void in asynchronous programming. - Explanation of the "move next" method as a state machine. - Caution against using async void in scenarios where exceptions need proper handling. 14:09 ⚠️ *Async Void in Constructors* - Addressing the issue of using async void in constructors. - Explanation of the limitations in constructors for asynchronous operations. - Introducing a workaround using async void but cautioning about potential issues. 16:21 🔄 *The Danger of Non-Awaited Tasks* - Identifying the dangers of not awaiting asynchronous tasks. - Highlighting the potential for simultaneous modifications leading to unexpected behavior. - Illustrating the challenges of catching exceptions in non-awaited tasks. 19:04 🔒 *Safeguarding Against Async Void Issues* - Emphasizing the risks associated with using async void. - Proposing safer alternatives, such as returning a Task or using async Task. - Encouraging developers to be mindful of potential issues with async void. 20:24 🚦 *Asynchronous Void Methods* - Avoid using `async void` methods. - Introduce the concept of "safe fire and forget" using an extension method. - The extension method handles exceptions and provides a clear indication of background execution. 22:58 🔄 *Refactoring the "Refresh" Method* - Discusses the importance of automatically refreshing the app on launch. - Introduces the concept of adding a delay to show an activity indicator, preventing a too-quick UI update. - Highlights the need to use cancellation tokens in async methods and demonstrates the use of `ConfigureAwait(false)`. 26:42 📡 *Calling External APIs* - Examines a method that calls an external API to get top stories. - Points out the issue of potentially blocking the main thread. - Introduces the use of `ConfigureAwait(false)` to avoid returning to the calling thread. 31:17 ⏳ *Handling Minimum Refresh Time* - Discusses the minimum refresh time and the usage of `Task.Delay`. - Warns against using `Task.Wait` due to its potential to freeze the UI thread. - Advocates for using `await` instead of `Wait` for better exception handling. 37:02 🔄 *Utilizing IAsyncEnumerable* - Addresses making multiple API calls serially for top stories. - Introduces the concept of `IAsyncEnumerable` to parallelize API calls. - Compares and contrasts the traditional approach with the improved asynchronous iteration using `await foreach`. 41:37 📱 *Introduction to Async/Await and User Experience* - Importance of considering user experience in async operations. - Introducing the concept of async enumerable. - The need for implementing cancellation tokens for user interaction. 42:05 🔄 *Async Enumerables and Enumerator Cancellation Attribute* - Explanation of parameters in async enumerable methods. - Introduction to the enumerator cancellation attribute for cancellation tokens. - How the async enumerable handles cancellation internally. 44:20 🚀 *Optimizing Async Code with Task.WhenAny* - Transitioning from traditional loops to async enumerable using Task.WhenAny. - Utilizing Task.WhenAny to optimize background task handling. - Benefits of breaking down the iteration on task completion. 47:21 🛠️ *Refactoring Async Methods and Handling Cancellation Tokens* - Refactoring methods using async and configuring for better performance. - Leveraging cancellation tokens for better control over async operations. - Handling cancellation tokens in both async methods and async enumerables. 48:02 ⚙️ *Avoiding Unnecessary Context Switching* - Explaining the impact of async/await on thread switching. - Demonstrating the removal of async/await in specific scenarios. - Utilizing value tasks to defer context switching and improve performance. 49:50 🧯 *Handling Exceptions in Async Methods* - Highlighting the importance of handling exceptions in async methods. - Discussing the necessity of keeping async/await in certain scenarios. - Demonstrating the use of try-catch blocks and potential pitfalls. 53:16 🚦 *Understanding ConfigureAwait(false) and Synchronization Contexts* - Clarifying the role of ConfigureAwait(false) in asynchronous code. - Considering scenarios where ConfigureAwait(false) might not have an effect. - Awareness of synchronization contexts, especially in UI-related scenarios. 56:57 🔄 *Optimizing with ValueTask and Hot Path Considerations* - Introducing the concept of ValueTask for performance optimization. - Guidelines for using ValueTask in methods where the hot path avoids async. - Balancing performance gains with code readability and maintainability. Made with HARPA AI
@oaykac10 ай бұрын
I never seen like this explaining for ConfigureAwait and ValueTask. Thanks.
@asifbhat335510 ай бұрын
First ever easy explanation of i await with relevant examples, in an interactive way. Hats off!
@DanielTabuenca Жыл бұрын
It's worth noting that .WaitAsync(cancelToken) will not actually end or stop the task you are waiting on, it simply lets the code stop waiting by throwing an OperationCanceledException at the await point. If you have a long-running task, the task will continue to run, even after this exception was thrown in the calling "thread".
@zzzzz290310 ай бұрын
So you are saying the background task will continue to run, but the awaiter will get an exception? So this case the awaiter has to "kill" the long running task?
@ZackJJones9 ай бұрын
@@zzzzz2903 I believe what he means is the system you were awaiting will continue processing, even though the calling system is no longer waiting for it. Eg, lets say you have an abstraction to call a long database operation. This abstraction doesn't have a means to pass a cancellation token, so you slap on waitAsync. If you started the db operation, but then throw the cancellation token, your calling system will stop awaiting the database operation, but the database is unaware of the cancellation and will continue its operation. So you can say waitAsync will only 'cancel' up, but not down in the stack. Whereas, with typical cancellation token usage, the database would recognize the cancellation and halt its operation as well.
@andrewshirley924011 ай бұрын
33:20 - "Every time you use .Wait, you're using 2 threads instead of 1". Not quite. Every time you use .Wait, you're using 1 thread (blocked waiting on IO) instead of 0 (where a thread is given back once the IO has completed). It isn't twice as bad, it is actually just infinitely worse. This is why the difference of async/await alone made the difference between "server crashes if you consistently send 5 requests a second" to "can handle 500+ requests/second easily" on a project I worked on once.
@romanokeser11 ай бұрын
good point, thank you for the explanation because I was also confused by that statement and couldn't find relative info on google, thanks
@ragtox Жыл бұрын
Great talk! Loved the energy as well.
@stephenyork7318 Жыл бұрын
Awesome video. I’ve not seen anyone go into the real reasons behind why things are done. The void return thing was particularly interesting.
@CRBarchager Жыл бұрын
So many good pointers in this talk. Way worth the watch if you're doing any async code.
@damaddog80653 ай бұрын
Task and Task have a Exception property, if this is NOT NULL and you do not OBSERVE IT, check it when the task goes out of scope or worse when the Garbage Collector comes and calls finalize on the task, it will throw. If you throw in finalizer, you are done. Else, you are probably still done unless you have an application level exception handler.
@robertmckee92728 ай бұрын
Ugh. I really wish people would stop explaining async/await wrong. And this guy makes one very big mistake that causes a ton of problems. The thread switch DOES NOT HAPPEN AT THE AWAIT KEYWORD. Why he felt he had to call that out @2:20 when that isn't how it works, I don't know. It's plain WRONG. The thread (Thread 1) does indeed go into DownloadDataTaskAsync and only comes out once it (and all of the child method it calls) also return from their very first await AND THEN it goes away. That is a huge difference. It is also why the compiler will warn you whenever you create an async method, but never use await inside of it, that "this method does not await and will run synch" or something very close to it. And then he repeats it @16:53 so it wasn't a mistake, it works differently than he explains.
@Laggie74 Жыл бұрын
Thanks for the presentation. It was very informative.
@tileq10 ай бұрын
Unfortunately, the lecturer does not understand well how async/await works. There is no second or background thread doing the work after the 'await' keyword. For anyone interested in the topic, there is a very famous article about that - ' There is no thread' by Stephen Cleary, a must-read for everyone interested in the topic.
@PaulSebastianM8 ай бұрын
Async/Await Tasks does use a separate thread if available, and if launched with Task.Run and similar methods. So he is not wrong. Just omitted some technical details for the sake of making a point.
@leotohill39417 ай бұрын
@@PaulSebastianM Task.Run is a special case that yes, Task.Run() explicitly uses a separate thread. But the principal case of await/async, as described in this presentation, does not.
@MyGroo Жыл бұрын
38:17 Doesn't seem like a reasonable use case for `FrozenSet`. Isn't the set unordered? Also, according to MSDN: "FrozenSet is immutable and is optimized for situations where a set is created infrequently but is used frequently at run time. It has a relatively high cost to create but provides excellent lookup performance. Thus, it is ideal for cases where a set is created once, potentially at the startup of an application, and is used throughout the remainder of the life of the application."
@cheebadigga4092 Жыл бұрын
even so, he's sorting it by points for UI presentation, the set order doesn't matter here
@kamaldesai9334 ай бұрын
Very easy to understand. Cheers !
@antonbegun231911 ай бұрын
Cool video. Many practical cases. It is very useful. I really liked AsyncEnumerable example, it is great. Thanks.
@earthlingthings3 ай бұрын
Thank you bro. You helped me understand and fix totally weird bugs.
@shadowthehedgehog2727 Жыл бұрын
Wouldn't it be better to not call Refresh in the constructor at all? Maybe call it in a initialize override function of the viewmodel? I'm at 22:38 so he may address this in the later part of the video.. will keep watching
@sgwong51311 ай бұрын
really good presentation. its feel short for 1 hour because lots of content and very fun presentation. I really learn some new stuff on async await which I never aware of.
@philyjayjohnny Жыл бұрын
Something that was not explained or I missed is that when operating on the viewmodel and switching threads, how he prevents race conditions and stuff... Like when ContinueAwait(false) continues on another thread, and the following code modifies some collection. If my memory serves me, using a classic List or an ObservableCollection from different threads, would be considered a dangerous practice, unless he uses some special concurrent collection? I'm confused.
@kirillxt Жыл бұрын
The talk ignores race conditions which is a bit meh. Part of why ConfigureAwait(false) isn't the default is because you're less likely to shoot yourself in the foot that way because your data structure accesses are synchronized across all async methods that are called by the UI thread (unless you access them in something like Task.Run()). That's why it's called SynchonizationContext
@TomRaf3 ай бұрын
Really enjoyed this, the explanation and also presentation was great! I wish everyone at my work watched this to avoid creating silly (sometimes driving crazy) bugs... Just waiting when I get fired after all that refactoring I've done recently, should see those PRs maaan :D
@richardhowells553111 ай бұрын
Hi Brandon, I am wondering if I have a misconception about what await does. My understanding is that in… X = await f(); … the call to f is synchronous. There is NO new thread creation at this point. I think that is contrary to what you said in your talk. Unless I misunderstood I believe that you said “…f() would run on some other thread grabbed from the thread pool…”. I understand the await to act as a gatekeeper - “You cannot come past here until the Task is completed.”. If there is an await in f() it returns an uncompleted Task, and this is passed up the call stack until eventually the run-time can allow the thread to be used for other work. AIUI to get a different (not necessarily new) thread for f() you have to use Task.Run(). Even then Task.Run’s behaviour is influenced by the currently active scheduler and so might not give a different thread. I think to guarantee a new thread requires using Task.Factory.StartNew with TaskScheduler.Default. Something like Task.Factory.StartNew(someAction, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); Do I have this wrong?
@rafedel-issa604211 ай бұрын
That's also what I'm wondering. From what I understand, after you call await, the code inside of the async function is "switched" on, so the current thread returns after calling await, and it will be able to handle executing other things that are queued up, but when it doesn't have anything to do, it will return back to the code inside of the async and execute that, then execute the remainder of the code after the await. I might have a misconception about this though.
@robertschmidt-cisternas80545 ай бұрын
You've understood it better than the presenter - after all these years, he's still confusing threads and Tasks. It's a pity that he continues to confuse people with these otherwise engaging and interesting talks.
@aluriramakrishna10 ай бұрын
awesome presentation on async/await.
@nepalxplorer Жыл бұрын
Learned a lot, thanks!
@ZdenoTirc Жыл бұрын
Still same misconceptions. For example, first example with WebClient, Thread 2 doesn't run DownloadDataTaskAsync. There is no thread, which is one of the main principle of async code
@eddypartey1075 Жыл бұрын
It seems like you misunderstood. Brandon didn't say that there were 2 threads at the same time. Even more he said "thread returns" at 2:30.
@ZdenoTirc Жыл бұрын
@@eddypartey1075 No, Brandon is wrong. Thread1 hits await keyword and returns, but Thread2 doesn't run DownloadDataTaskAsync(there is no thread, it is async).
@bass-tones Жыл бұрын
I had the same exact thought, intuitively. Stephen Cleary has a blog post about this topic called “There is No Thread.” Now it is an old post, and it’s possible something has changed, but I’m almost certain not. There doesn’t need to be a second thread for true async work because it gets handled by the OS. Amazing how even a lecture on async misconceptions opens right out of the gate with a hugely common misconception.
@bogdan.p7 ай бұрын
then how are you able to run 2 pieces of code at the same time if there is no second thread? I mean you can literraly run the UI thread while doing work in the background. They kind of work together even tho concurrency and asyncronous are not the same.
@ZdenoTirc7 ай бұрын
@@bogdan.p DownloadDataTaskAsync in first example is asynchronous operation and If operation is natively asynchronous, then there is no other thread doing something and also UI thread is not blocked during await (if it is app with UI thread).
@GhostTyper Жыл бұрын
Task.Delay() doesn't preserve a thread to wait. XD I think it uses something like TaskCompletionSource and gets kicked of, when time is there, so waiting synchronously via Wait() doesn't consume two threads.
@whitek6532 Жыл бұрын
Always should use await even if your method just return the task since you will lose stack trace
@cheebadigga4092 Жыл бұрын
not in this case, he's calling await from the calling method, so the stack trace will still be clear I think
@haroldpepete8 ай бұрын
In my humble opinion, this's one of the best talk i have ever watched, this guy goes straight to the point, Nick Chapsas or whatever his name is, has to be learn something of this guys, Nick talks 90% of things that nothing have to do with the main talk, less nick speakers and more Brandon Minnick
@mobe65248 ай бұрын
Nick shares some really good stuff actually. He gives advices, talks about incoming features, shows some implementations. Perhaps you were disappointed in his logging talk, there was still great tips there. You may wanna check out his channel, very rich content. But yeah, this presentation was interesting.
@livingdeathD7 ай бұрын
They are different ways, the truth is I enjoy both types of talks
@PeacefulMindss Жыл бұрын
Super clear and helpful, thank you.
@TheAzerue Жыл бұрын
Thank you for wonderful talk
@ppcuser10010 ай бұрын
A very useful brief on Async/Await. The awesome lecturer explaining clear and short 👍
@eddypartey1075 Жыл бұрын
Very helpful and lucid, great job!
@divyaprakashjha838911 ай бұрын
Is news service code shown in the video somewhere in GitHub?
@ondrejexner3688 Жыл бұрын
One of the best Async/Await presentation under 1h! Really. I just have one question ... What about a use-case when you would have like 1000 TOP stories instead of just 50. Is it still a good idea to fire all 1000 tasks at once? I think not, because it can lead to treadpool starvation. So maybe fire just 50 tasks and then fire new ones only when one of the running threads returns? Or is there a better way to handle this use-case?
@S3Kglitches Жыл бұрын
are you sure? just in the second minute, there is clearly a mistake. Calling WebClient.xxxAsync does not start a new thread unless it would be Task.Run(WebClient.xxxAsync).
@bullet9564 Жыл бұрын
You misunderstood async await! There’s no thread. The idea here is to NOT wait for completion of an IO activity - so, async await was created. You can read more here about it blog.stephencleary.com/2013/11/there-is-no-thread.html
@sachin3698711 ай бұрын
Use chunks
@tiosatria99193 ай бұрын
damn good explanation and video. kudos
@SuperGulamali Жыл бұрын
This is literal gold
@SamWashkansky Жыл бұрын
Please post the link to the source code repo
@microtech244811 ай бұрын
Nice explanation. Just wish ConfigureAwait(false) could be default by .Net team 😊
@PinheiroJaime Жыл бұрын
Talking about "best practices", CancellationToken as first parameter really hurt me.
@MrHeavyRunner Жыл бұрын
Probably just mistake, not intentional. Also he has them as last parameter in other methods.
@everyonesview Жыл бұрын
Awesome!👏👏👏👏
@FirstLast-gc6ss Жыл бұрын
46:38 Why Task.WhenAny ? What about pagination concept and only show first 20 or 30 records and than on page 2 click/scroll (infinite scroll) send 2nd request for another next 20 records?? Why all this fuss of When.Any ??
@Eupolemos11 ай бұрын
51:19 - how does he do that?
@yohm31 Жыл бұрын
So cool: I guess there was other ways to achieve progressive results to be yielded from async tasks, but now it's clever.
@markovcd11 ай бұрын
Sad that he moved on from the async in the constructor example as if he arrived at the best solution. This is spreading wrong information. Do not leave async initialization code in your constructors. What I tend to use is to introduce a method with a signature: "async Task Initialize(CancellationToken ct)" and call it from whatever wants to navigate to that view. He also missed other reason why you shouldn't do long running operations in the ctor - you don't always have control when it is called because of dependency injection framework.
@xybersurfer10 ай бұрын
i strongly disagree with the excuse of not running long running operations in the constructor. it's like saying that long running operations can't create anything. it's just a convenient lie, for the C# language designers, that actually harms how generic the language is. let programmers decide whether having a guaranteed initialized object is worth cost of waiting (which has to happen regardless, now it's just in the wrong place). i bet you it's worth it the majority of the time. i have similar but less strong feeling about the lack of async operations in properties
@pepperplume Жыл бұрын
first, also i was having async await issues, hopefully after this video, not anymore
@anandshindey Жыл бұрын
I wish they had a do and don't guide for beginners like me. This video confused me .
@martinprohn2433 Жыл бұрын
Instead of "always avoid 'return await', except …", it would be better to say: "Only avoid 'return await' in very simple statements (oneliners) and never in …".
@JustinMinnaar Жыл бұрын
Except for the incorrect usage of the ConfigureAwait(false); the talk is a nice summary of using async/await.
@everyonesview Жыл бұрын
Please yourself with regard to the incorrect usage of the ConfigureAwait(false)
@LeducDuSapin Жыл бұрын
Do you care to enlighten us, why the usage is incorrect? Or do you just purport it?
@petrkomarek724911 ай бұрын
Please share what in the presentation was incorrect exactly?
@alirezanet Жыл бұрын
Awesome talk 👏🙏💐
@CrisDevDotDot9 ай бұрын
OMG so this guys' last breath was at 59:59 . talk about being right on the dot in 1 hour 😅😅
@szeredaiakos11 ай бұрын
Safe fire and forget asyncs are nothing new but one cannot have enough talks of the subject.
@shreebatta9 ай бұрын
Async method/s in constructors cause deadlocks. It's just bad practice. Runtime that runs ctor doesn't know/doesn't care about ansynchronicity
@auronedgevicks7739 Жыл бұрын
I've been watching for 20mins and seriously considering this a waste of time. It's just a comedy of errors by not following how you should use async/await and then complaining about why it's being used the wrong way.
@S3Kglitches Жыл бұрын
This guy got the first thing wrong. Not worth watching the rest if he doesn't know precisely what he's talking about. 2:33 no this does not start a new thread. Assuming it is asynchronous I/O operation, the code will stop there and UI handling will be able to continue (which would be frozen if this weren't async/await but sync code).
@kingjustink Жыл бұрын
He never said it starts a new thread, just that another thread from the thread pool will perform the async operation
@ZdenoTirc Жыл бұрын
@@kingjustink and exactly that is not correct. there is not another thread from thread pool, which will perform async operation. if it is async, then there is no thread.
@auronedgevicks7739 Жыл бұрын
@@ZdenoTirc I think he was saying that the thread will be resumed by a different thread in the pool. Don't know if he's right or not but from what I know the thread context is captured so it can be resumed safely. not sure if it's the same thread that resumes or a different one.
@AmitTaparia2 ай бұрын
Just because you are using async and await doesn’t mean that the system will create additional threads like Thread 2 as mentioned in the first slides. It’s really misleading
@unexpectedkAs Жыл бұрын
That energy tho
@georgevolkov85992 ай бұрын
configureAwait(false) in 2024. Ok. Other part was nice)
@mhalan219811 ай бұрын
How come the unawait void will go back to the constructor? Is this guy from Microsoft? If so then the company has drama
@mohamedbeyremmakhlouf Жыл бұрын
Basic concept for a conference like NDC
@xybersurfer10 ай бұрын
it's good to go over the basics sometimes. but i would say it that this is a bit above the basics. it's not what you would give to a beginning C# programmer
@pejmannikram734910 ай бұрын
At least the first explanation about Async is not 100% correct, the relation of async code and Thread are not 1 to 1 kzbin.info/www/bejne/n52cmJ9ugq1kbdU
@fr3ddyfr3sh Жыл бұрын
Wow, explaining two things wrong within the first 4 minutes. If you really want to understand async/await: watch a different video. Also he did not mention THE most important issue with async void: uncaught exceptions in async-void will immediately crash your app, you cannot do anything to prevent it. And due their async stack, finding the source of these crashes is difficult.
@kingjustink Жыл бұрын
what were the two things?
@GeorgeTsiros10 ай бұрын
who let this guy near a keyboard?
@tanoryjakaperdana14196 ай бұрын
If its common then it isnt mistake 😂
@oislek349 ай бұрын
tiring voice
@igorspitz7 ай бұрын
Very
@gregh559210 ай бұрын
I keep seeing this talk and it is plain awful. So many inaccuracies.