Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Wednesday, 25 September 2024

Should I use ConfigureAwait(true) or ConfigureAwait(false)?

 One of the most popular questions in the C# asynchronous programming world is when do I use 'ConfigureAwait(true)' and when do I use 'ConfigureAwait(false)'. Before moving deep in let me give you two simple rules which you should always keep in mind and should follow when writing async code in C#,

  • If you are writing code that updates the UI then set ConfigureAwait to true (ConfigureAwait(true))
  • If you are writing a library code that is shared and used by other people then set ConfigureAwait to false ( ConfigureAwait(false) )

Before getting further let me introduce a few basic concepts,

  • Code which follows await KeyWord is continuation task
  • Code above await keyword runs synchronously on the main thread (Eg: UI thread)
  • The async method runs on another thread, usually a worker thread (To unblock the main thread, for example, UI thread)
  • Task.Wait() will wait synchronously and block the main thread ( You should never use Task.Wait() )

To make this article super simple I am deliberately skipping the complexity of SynchronizationContext but it is worth reading, though it is not required to understand the topic of this article.

Now the question is which thread does the Continuation task run? Will it be the main thread (Eg: UI thread) or the same thread as the asynchronous method? This is where we set 'ConfigureAwait' to true or false to decide which thread the continuation task executes on. If we set 'ConfigureAwait(true)' then the continuation task runs on the same thread used before the 'await' statement. If we set 'ConfigureAwait(false)' then the continuation task runs on the available thread pool thread.

What is the purpose of running the continuation task using the main thread which was used before the await statement? Let me explain it with a simple UI application. Before getting your hands dirty one thing you should always keep in mind is UI controls can update only using the UI thread. With that let's jump straight into the code, which is a simple WPF application,

No alt text provided for this image

In the above lines of code when the control hits the 'await' statement (line number 32), it releases/unblocks the UI thread and calls "DoSomethingAsync" method, and waits asynchronously. Also, it instructs to run the continuation task (lines after await statement) on any available thread (Not forced to run on UI thread) by setting configure await to false ( ConfigureAwait(false) ). After waiting for 1 second (line number 39) the control returns and runs the continuation task and the continuation task tries to update the textbox text to a new value (line number 34) which is possible only using UI thread but as we instruct to use any available thread pool thread to run continuation task ( by setting ConfigureAwait(false) ) it fails with the error,

No alt text provided for this image

This error is obvious because no other thread other than the UI thread is allowed to update UI control but here it is some other thread trying to do update the UI hence it failed.

Now let's see what happens when we set 'ConfigureAwait(true)', which is the default,

No alt text provided for this image
No alt text provided for this image

and now the result is as expected, which updates the textbox with the new value. Here 'ConfigureAwait(true)' did the magic, which forced the continuation task to use the UI thread hence updated the UI properly. This is exactly why the rule is "If you are writing code on the UI then set ConfigureAwait to true".

Now let's see why it is a good idea to set ConfigureAwait to false if you are writing library code that is shared with other developers. Let's modify the same example we had before,

No alt text provided for this image

Imagine the method "DoSomethingAsync" is the part of a shared library and "ConfigureAwait" is not set to false in Task.Delay(1000) (Line number 38). As this is a shared library method you have no idea how the developers are going to use this method. If the developer asynchronously waits for the method ( await DoSomethingAsync() ) then everything is well and good as there won't be a blocking thread. But you cannot guarantee that all developers do the same.

What if somebody synchronously waits for "DoSomethingAsync" like DoSomethingAsync().Wait(), which you as a developer should never do. When you call "Wait" method of a "Task" it blocks the thread and waits synchronously.

Let's see line by line the sample code we have. On line number 32 it calls "DoSomethingAsync" and when it hit line number 38 ( on Task.Delay(1000) ) it asynchronously waits and returns "Task" to line number 32 and there it calls "Wait" method. What "Wait" method does is it synchronously waits and blocks the main thread. After one second of delay (Line number 38), it wants to do the continuation task which is line number 40. As we didn't set configure await to false (default is true) it is expecting the same thread which was used before running the task but that thread is blocked because of "DoSomethingAsync().Wait()". Can you guess what we call for this situation? Nothing but a deadlock. The only way to solve this problem is not to force the continuation task to use the same thread which used before, which can do by setting ConfigureAwait to false as below,

No alt text provided for this image

Now regardless of how people use your library the continuation task will never be blocked that is exactly why the rule is "If you are writing library code that is shared and used by other people the set ConfigureAwait to false ( ConfigureAwait(false) )"

Monday, 26 August 2024

Code Review Guide lines

 1- Readable

2- Performance (dev vs prod) 3- Reusable code 4- Naming convention - variables, classes, properties, functions Eg, GetEmployee >> GetEmployeeList ----- both conveying same meaning but first is small 5- DRY principle - Don't repeat yourself -- create helper classes/ function and reuse 6- Class names, Method names: PascalCase 7- Variables: camelCase 8- Keep methods small and simple. Don't make it too large. Keep it short and simple. If it's too short, split its functionality and call the function in actual function.. 9- Create self explanatory method names so that you don't need to write comments


Code Review Checklist:

  1. Logging
  2. Monitoring
  3. Scale
  4. Traceability
  5. Troubleshooting
  6. Reporting
  7. UX
  8. Incorrect problem definition
  9. Time management
  10. Ignoring other features.
  11. Focusing on today needs.
  12. Alerting
  13. Metrics
  14. Testing
  15. Deployment
  16. Code cleanup
  17. Latency
  18. No design review
  19. No customer review
  20. Concurrency
  21. Simple bugs
  22. Mutation
  23. Readability
  24. Naming
  25. Documentation (motivation)
  26. Audit
  27. Security
  28. Complex if-then logic
  29. Suspicious loop 'break'
  30. Negative logic
  31. Regexp - long input could cause issues.
  32. Nulls
  33. More than 3 arguments
  34. Line length
  35. Shared resources abuse
  36. Cache (think hard)
  37. Variable name length
  38. Commit message
  39. Squash if needed
  40. Build time change
  41. "Random" usage smell
  42. Open Close principle
  43. Code duplication
  44. OverComplexity (ex. Types where string is enough)
  45. UnderComplexity (ex. strings where type is required)
  46. Bulk test fail smell
  47. Backward compatibility
  48. Forward compatibility
  49. API no version
  50. Incorrect db type usage
  51. Adding indexes instead of search engine view
  52. Ignoring Failures
  53. Expecting feature would work
  54. Too verbose error handling
  55. Sensitive info in logs
  56. Missing "main" flow
  57. Feature toggle (if needed)
  58. Dependencies (collisions? new one?)
  59. Comments smell
  60. Dependent Teams
  61. Plural/Singular correctness
  62. Consistency with codebase conventions
  63. Revert implications
  64. Either simple MultiReturn or Single
  65. Time to understand code smell

Wednesday, 21 August 2024

List vs Dictionary in C#

 

List vs Dictionary in C# with Examples

In this article, I am going to discuss List vs Dictionary in C# with Examples. Please read our previous article where we discussed Conversion Between Array List and Dictionary in C#. At the end end of this article, you will understand the difference between a List and Dictionary as well as you will understand when to use a List over Dictionary and vice-versa.

List vs Dictionary in C#

Both lists and dictionaries belong to Generics collections that are used to store collections of data. Both Dictionary <TKey, TValue> and List <T> are similar both have random access data structures on top of the .NET framework. The Dictionary is based on a hash table which means it uses a hash lookup, which is an efficient algorithm to look up things, on the other hand, a list, has to go and check element by element until it finds the result from the beginning. In this article, we will discuss List vs Dictionary in C#. When comparing with the List data structure, the dictionary always has a more or less fixed lookup time.

Let’s go into the details.

The Dictionary uses the hashing algorithm to search for the element (data). A Dictionary first calculates a hash value for the key and this hash value leads to the target data bucket. After that, each element in the bucket needs to be checked for equality. But actually, the list will be faster than the dictionary on the first item search because nothing to search for in the first step. But in the second step, the list has to look through the first item and then the second item. So each step of the lookup takes more and more time. The larger the list, the longer it takes. Of course, the Dictionary in principle has a faster lookup with O(1) while the lookup performance of a List is an O(n) operation.

The Dictionary maps a key to a value and cannot have duplicate keys, whereas a list just contains a collection of values. Also, Lists allow duplicate items and support linear traversal.

Consider the following example:
Dictionary<string, int> dictionary = new Dictionary<string, int>();
List<int> newList = new List<int>();

Advertisements

Add data to the list
newList.Add(data);

A list can simply add the item at the end of the existing list item. Add data to the Dictionary
dictionary.Add(key, data);

When you add data to a Dictionary, you should specify a unique key to the data so that it can be uniquely identified.

A Dictionary has a unique identifier, so whenever you look up a value in a Dictionary, the runtime must compute a hash code from the key. This optimized algorithm is implemented by some low-level bit shifting or modulo divisions. We determine the point at which Dictionary becomes more efficient for lookups than List.

Example to understand List vs Dictionary in C#:

The Find() method of the List class loops thru each object in the list until a match is found. So, if we want to look up a value using a key, then a dictionary is better for performance over the list. So, we need to use a dictionary when we know the collection will be primarily used for lookups. 

using System;
using System.Collections.Generic;
namespace DictionaryVSListCollectionDemo
{
public class Program
{
public static void Main()
{
Country country1 = new Country()
{
Code = "AUS",
Name = "AUSTRALIA",
Capital = "Canberra"
};
Country country2 = new Country()
{
Code = "IND",
Name = "INDIA ",
Capital = "New Delhi"
};
Country country3 = new Country()
{
Code = "USA",
Name = "UNITED STATES",
Capital = "Washington D.C."
};
Country country4 = new Country()
{
Code = "GBR",
Name = "UNITED KINGDOM",
Capital = "London"
};
Country country5 = new Country()
{
Code = "CAN",
Name = "CANADA",
Capital = "Ottawa"
};
//List<Country> listCountries = new List<Country>();
//listCountries.Add(country1);
//listCountries.Add(country2);
//listCountries.Add(country3);
//listCountries.Add(country4);
//listCountries.Add(country5);
Dictionary<string, Country> dictionaryCountries = new Dictionary<string, Country>();
dictionaryCountries.Add(country1.Code, country1);
dictionaryCountries.Add(country2.Code, country2);
dictionaryCountries.Add(country3.Code, country3);
dictionaryCountries.Add(country4.Code, country4);
dictionaryCountries.Add(country5.Code, country5);
string strUserChoice = string.Empty;
do
{
Console.WriteLine("Please enter country code");
string strCountryCode = Console.ReadLine().ToUpper();
// Find() method of the list class loops thru each object in the list until a match is found. So, if we want to
// lookup a value using a key dictionary is better for performance over list.
// Country resultCountry = listCountries. Find(country => country.Code == strCountryCode);
Country resultCountry = dictionaryCountries.ContainsKey(strCountryCode) ? dictionaryCountries[strCountryCode] : null;
if (resultCountry == null)
{
Console.WriteLine("The country code you entered does not exist");
}
else
{
Console.WriteLine("Name = " + resultCountry.Name + " Captial =" + resultCountry.Capital);
}
do
{
Console.WriteLine("Do you want to continue - YES or NO?");
strUserChoice = Console.ReadLine().ToUpper();
}
while (strUserChoice != "NO" && strUserChoice != "YES");
}
while (strUserChoice == "YES");
}
}
public class Country
{
public string Name { get; set; }
public string Code { get; set; }
public string Capital { get; set; }
}
}
Output:

List vs Dictionary in C#

In the next article, I am going to discuss Generic Stack Collection Class in C# with Examples. Here, in this article, I try to explain List vs Dictionary in C# with an example. I hope this article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this article.

Recent Post

how to control duplicate order