C# Developers: Stop Calling .Result
I love async/await Task based programming! I talk about it in all my demos, it is in all my libraries, and Frank and I did a whole Merge Conflict podcast episode on it. The problem is that I keep getting bug reports and seeing samples where it is being abused and used completely wrong. I am never a fan of calling a lot of async code in a constructor or in the OnCreate/AppDelegate, but the real issue is when I see stuff like this with .Result:
public App()
{
try
{
_locator.StartListeningAsync(TimeSpan.FromSeconds(30), 100);
var position = _locator.GetPositionAsync().Result;
if (position != null)
{
App.lat = position.Latitude;
App.lon = position.Longitude;
}
}
catch (Exception c)
{
}
MainPage = GetMainPage();
}
AHHHHHH!!! We aren't letting StartListeningAsync
finish, and we are doing a .Result essentially locking the entire app start code! This makes me the saddest panda in the entire world.
Recently Jon Goldberger wrote a great article on getting started with async/await, but going way back 6 years ago, Stephen Toub from Microsoft 6 wrote an amazing article explaining how to use async/await when dealing with the UI and with event handlers. Both articles are great reads and yes even the 6 year old blog applies to this day.
Stephen's article boils down to this:
On your UI thread, instead of writing:
Task s = LoadStringAsync();
textBox1.Text = s.Result; // BAD ON UI
you can write:
Task s = LoadStringAsync();
textBox1.Text = await s; // GOOD ON UI
Or instead of writing:
Task t = DoWork();
t.Wait(); // BAD ON UI
you can write:
Task t = DoWork();
await t; // GOOD ON UI
Essentially calling .Result or .Wait will lock up your UI! It is true! So true that I made an entire video right here explaining why you need to stop using .Result!