<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ahmed_Greynoon</title>
    <description>The latest articles on Forem by Ahmed_Greynoon (@a_greynoon).</description>
    <link>https://forem.com/a_greynoon</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F125270%2Fb4370284-4a68-4dbf-b49b-61d0b87934d4.png</url>
      <title>Forem: Ahmed_Greynoon</title>
      <link>https://forem.com/a_greynoon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/a_greynoon"/>
    <language>en</language>
    <item>
      <title>Getting Started with Asynchronous Programming in Dart</title>
      <dc:creator>Ahmed_Greynoon</dc:creator>
      <pubDate>Sat, 07 Sep 2024 19:59:53 +0000</pubDate>
      <link>https://forem.com/a_greynoon/getting-started-with-asynchronous-programming-in-dart-425</link>
      <guid>https://forem.com/a_greynoon/getting-started-with-asynchronous-programming-in-dart-425</guid>
      <description>&lt;p&gt;Last &lt;a href="https://dev.to/a_greynoon/asynchronous-synchronous-programming-in-dart-5h95"&gt;article&lt;/a&gt;, we've covered the foundational concepts of the asynchronous programming model, and we learn that synchronous programming in Dart is a powerful way to keep your applications responsive, especially when dealing with tasks like I/O operations, network requests, or heavy computations that could otherwise block the main thread.&lt;/p&gt;

&lt;p&gt;Now it's time to dive into how to implement asynchronous code in Dart.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does asynchronous code matter?
&lt;/h2&gt;

&lt;p&gt;Asynchronous operations let your program complete work while waiting for another operation to finish. Here are some common asynchronous operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetching data over a network.&lt;/li&gt;
&lt;li&gt;Writing to a database.&lt;/li&gt;
&lt;li&gt;Reading data from a file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Such asynchronous computations usually provide their result as a &lt;code&gt;Future&lt;/code&gt;, and to interact with these asynchronous results you can just use callback, or the &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; keywords. These allow you to write code that performs non-blocking operations, ensuring that your application remains responsive and efficient, even when handling time-consuming tasks.&lt;/p&gt;

&lt;p&gt;Don't worry, you will understand that now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;A future is an object that represents the result of an asynchronous operation, which will return a value at a later time. They can be thought of as a promise that there will be a value or an error at some point.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The future has two states: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Completed. &lt;/li&gt;
&lt;li&gt;Uncompleted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When asynchronous operation is completed, it will return a value if it is successful or it will return an error in the future. But for the uncompleted future, it will eventually return as long as the asynchronous operation is still in progress.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example of a Future:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String createOrderMessage() {
  var order = fetchUserOrder();
  return 'Your order is: $order';
}

Future&amp;lt;String&amp;gt; fetchUserOrder() {
  return Future.delayed(
    const Duration(seconds: 2),
    () =&amp;gt; 'Large Latte',
  );
}

void main() {
  print(createOrderMessage());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your order is: Instance of 'Future&amp;lt;String&amp;gt;'

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the asynchronous code works fine but it fails to get the value, here's why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fetchUserOrder()&lt;/code&gt; function is an asynchronous, after the 2 sec delay it will provide a string that describes the user's order: a "Large Latte".&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;print()&lt;/code&gt; inside the &lt;code&gt;main()&lt;/code&gt; will get the user's order by operating&lt;code&gt;createOrderMessage()&lt;/code&gt; function, which should call &lt;code&gt;fetchUserOrder()&lt;/code&gt; and wait for it to finish. &lt;/li&gt;
&lt;li&gt;Because &lt;code&gt;createOrderMessage()&lt;/code&gt; does &lt;em&gt;not&lt;/em&gt; wait for &lt;code&gt;fetchUserOrder()&lt;/code&gt; to finish, &lt;code&gt;createOrderMessage()&lt;/code&gt; fails to get the string value from &lt;code&gt;fetchUserOrder()&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;So, &lt;code&gt;createOrderMessage()&lt;/code&gt; got a representation of pending work to be done: an &lt;strong&gt;uncompleted future&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  So... how to get the value from a future?
&lt;/h2&gt;

&lt;p&gt;There are two ways to get value in the future:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using a callback.&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; keywords.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  First: Using Callback
&lt;/h3&gt;

&lt;p&gt;When a future completes, you can run a callback to handle the result by using these methods: &lt;code&gt;then()&lt;/code&gt;, &lt;code&gt;catchError()&lt;/code&gt;, and &lt;code&gt;whenComplete()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can use &lt;code&gt;then()&lt;/code&gt; when the future completes successfully with a value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void main() {
  print('start fetching data');

  Future&amp;lt;String&amp;gt;.delayed(Duration(seconds: 2), () {
    return 'data are fetched';
  }).then((value) {
    print(value);
  });

  print('end fetching data');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;start fetching data
end fetching data
data are fetched
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But when the future completes with an error value, you can handle it by using the&lt;code&gt;catchError()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void main() {
  print('start fetching data');

  Future&amp;lt;String&amp;gt;.delayed(Duration(seconds: 2), () {
    return 'data are fetched';
  }).then((value) {
    print(value);
  }).catchError((error) {
  print(error);
});

print('end fetching data');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;start fetching data
end fetching data
data are fetched
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's another example of using &lt;code&gt;catchError()&lt;/code&gt; that will make you understand more:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Future&amp;lt;int&amp;gt; fetchNumber(bool succeed) {
  return Future.delayed(Duration(seconds: 2), () {
    if (succeed) {
      return 42;
    } else {
      throw Exception("Failed to fetch number");
    }
  });
}

void main() {
  fetchNumber(false).then((value) {
    print("The number is $value");
  }).catchError((error) {
  print("Error occurred: $error");
  });
  print("Waiting for the number...");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Waiting for the number...
Error occurred: Exception: Failed to fetch number
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fetchNumber()&lt;/code&gt; function returns a &lt;code&gt;Future&lt;/code&gt; (which is a number) that simulates an asynchronous operation using &lt;code&gt;Future.delayed&lt;/code&gt;, and after 2 seconds it throws an exception if the &lt;code&gt;succeed&lt;/code&gt; value equal to &lt;code&gt;false&lt;/code&gt; to simulate an error in the operation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;catchError()&lt;/code&gt; method will handle any errors that occur during the execution of the &lt;code&gt;Future&lt;/code&gt;, Method After calling &lt;code&gt;fetchNumber()&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also when a future completes with a value or an error, you can just use &lt;code&gt;whenComplete()&lt;/code&gt; method. In other words, the callback &lt;code&gt;whenComplete()&lt;/code&gt; method will always execute whether the future succeeds or not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Future&amp;lt;int&amp;gt; fetchNumber(bool succeed) {
  return Future.delayed(Duration(seconds: 2), () {
    if (succeed){
      return 42;
    } else {
     throw Exception("Failed to fetch number");
    }
  });
}

void main() {
  fetchData(false).then((value) {
    print(value);
  }).catchError((error) {
    print("Error occurred: $error");
  }).whenComplete(() {
    print("Operation complete, cleaning up...");
  });

  print("Waiting for the operation to complete...");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Waiting for the operation to complete...
Error occurred: Exception: Failed to fetch number
Operation complete, cleaning up...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Second: Using &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; keywords.
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; keywords provide a declarative way to define asynchronous functions and use their results. Remember these two basic guidelines when using &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To define an &lt;code&gt;async&lt;/code&gt; function, add &lt;code&gt;async&lt;/code&gt; before the function body.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;await&lt;/code&gt; in front of any expression within an &lt;code&gt;async&lt;/code&gt; function to wait for it to complete.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;await&lt;/code&gt; keyword works only in &lt;code&gt;async&lt;/code&gt; functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'dart:async';


Future&amp;lt;String&amp;gt; fetchData() async {
  await Future.delayed(Duration(seconds: 2));
  return 'Data fetched successfully!';
}

Future&amp;lt;void&amp;gt; main() async {
  print('Fetching data...');

  String result = await fetchData();

  print(result);

  print('Done fetching data.');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fetching data...
Data fetched successfully!
Done fetching data.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Explanation:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The&lt;code&gt;fetchData()&lt;/code&gt; function is an &lt;code&gt;async&lt;/code&gt; function which simulates fetching a data from a server and delay the result using &lt;code&gt;Future.delayed(Duration(seconds: 2))&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;await&lt;/code&gt; keyword is used before &lt;code&gt;Future.delayed&lt;/code&gt;, which causes the function to pause for 2 seconds before returning the result.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;main()&lt;/code&gt; function is also &lt;code&gt;async&lt;/code&gt; because it uses the &lt;code&gt;await&lt;/code&gt; keyword before &lt;code&gt;fetchData()&lt;/code&gt;, which means the &lt;code&gt;main()&lt;/code&gt; function will pause execution until &lt;code&gt;fetchData()&lt;/code&gt; completes.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;print('Done fetching data.')&lt;/code&gt; line will execute only after &lt;code&gt;fetchData()&lt;/code&gt; has returned its result.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember: &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; are one of the ways to get the value after the &lt;code&gt;Future&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Error handling in asynchronous functions
&lt;/h2&gt;

&lt;p&gt;Handling errors is crucial in asynchronous programming, you can use &lt;code&gt;try-catch&lt;/code&gt; block with &lt;code&gt;async&lt;/code&gt; functions to capture any errors that occur during the execution of the &lt;code&gt;await&lt;/code&gt; Future.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Future&amp;lt;void&amp;gt; printOrderMessage() async {
  try {
    print('Awaiting user order...');
    var order = await fetchUserOrder();
    print(order);
  } catch (err) {
    print('Caught error: $err');
  }
}

Future&amp;lt;String&amp;gt; fetchUserOrder() {

  // Imagine that this function is more complex.
  var str = Future.delayed( const Duration(seconds: 4), () {
    throw 'Cannot locate user order';
  });
  return str;
}

void main() async {
  await printOrderMessage();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Awaiting user order...
Caught error: Cannot locate user order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, you can handle the errors by using callback methods: &lt;code&gt;then()&lt;/code&gt;, &lt;code&gt;catchError()&lt;/code&gt;, and &lt;code&gt;whenComplete()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's an example of that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Future&amp;lt;void&amp;gt; printOrderMessage() {
  print('Awaiting user order...');
  return fetchUserOrder().then((order) {
     print(order);
  }).catchError((err) {
    print('Caught error: $err');
  });
}

Future&amp;lt;String&amp;gt; fetchUserOrder() {

  // Imagine that this function is more complex.
  return Future.delayed(const Duration(seconds: 4), () {
    throw 'Cannot locate user order';
  });
}

void main() {
  printOrderMessage();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Awaiting user order...
Caught error: Cannot locate user order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  So... what is the difference between both examples?
&lt;/h2&gt;

&lt;p&gt;The main difference between using &lt;code&gt;async/await&lt;/code&gt; and using &lt;code&gt;then()/catchError()&lt;/code&gt; lies in how the asynchronous code is written and how it affects readability, maintainability, and error handling.&lt;/p&gt;

&lt;p&gt;For instance, the &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; syntax makes the code more readable and easier to follow, while &lt;code&gt;then()&lt;/code&gt;/&lt;code&gt;catchError()&lt;/code&gt; syntax involves chaining method calls, which can become less readable with more complex asynchronous operations.&lt;/p&gt;

&lt;p&gt;In error handling, &lt;code&gt;try&lt;/code&gt;/&lt;code&gt;catch&lt;/code&gt; is straightforward and similar to handling errors in synchronous code,  while &lt;code&gt;then()&lt;/code&gt;/&lt;code&gt;catchError()&lt;/code&gt; error handling can sometimes be less intuitive especially when handling multiple asynchronous calls.&lt;/p&gt;

&lt;p&gt;But, that doesn't mean using calling back methods are bad approach, as we said earlier it lies in how the asynchronous code is written and how it affects readability, maintainability, and error handling.&lt;/p&gt;

&lt;p&gt;Do want more? here's another example :&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetching data from the API server
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Using callback methods: &lt;code&gt;then()&lt;/code&gt;, &lt;code&gt;catchError()&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:http/http.dart' as http;
import 'dart:convert';


void fetchDataUsingCallbacks() {
  final url = Uri.parse('https://jsonplaceholder.typicode.com/posts/1');

  http.get(url).then((response) {
    if (response.statusCode == 200) {

    var data = jsonDecode(response.body);
    print('Data fetched successfully: ${data['title']}');

  } else {
    print('Failed to load data');
  }

  }).catchError((error) {
    print('An error occurred: $error');

  }).whenComplete(() {
    print('Request complete.');
  });
}


void main() {
  fetchDataUsingCallbacks();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Data fetched successfully: sunt aut facere repellat provident occaecati excepturi optio reprehenderit
Request complete.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Error Case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;An error occurred: &amp;lt;error message&amp;gt; 
Request complete.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Using &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; keywords with  &lt;code&gt;try()&lt;/code&gt;, &lt;code&gt;catch()&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:http/http.dart' as http;
import 'dart:convert';


Future&amp;lt;void&amp;gt; fetchDataUsingAsyncAwait() async {
  final url = Uri.parse('https://jsonplaceholder.typicode.com/posts/1');

  try {
    final response = await http.get(url);

    if (response.statusCode == 200) {

      var data = jsonDecode(response.body);
      print('Data fetched successfully: ${data['title']}');

    } else {
      print('Failed to load data');
    }

  } catch (error) {
    print('An error occurred: $error');
  } finally {
    print('Request complete.');
  }
}


void main() async {
  await fetchDataUsingAsyncAwait();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Data fetched successfully: sunt aut facere repellat provident occaecati excepturi optio reprehenderit
Request complete.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Error Case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;An error occurred: &amp;lt;error message&amp;gt; 
Request complete.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Previously in the last couple of articles, we learn what are we have delved into the intricacies of asynchronous programming in Dart, exploring both the &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; syntax and the use of callback methods such as &lt;code&gt;then()&lt;/code&gt;, &lt;code&gt;catchError()&lt;/code&gt;, and &lt;code&gt;whenComplete()&lt;/code&gt;. We learned how asynchronous programming helps keep applications responsive and prevents blocking the main thread, especially during time-consuming operations like network requests or file I/O.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>mobiledevelopment</category>
      <category>asynchronous</category>
    </item>
    <item>
      <title>Asynchronous &amp; synchronous Programming In Dart</title>
      <dc:creator>Ahmed_Greynoon</dc:creator>
      <pubDate>Sun, 01 Sep 2024 06:24:58 +0000</pubDate>
      <link>https://forem.com/a_greynoon/asynchronous-synchronous-programming-in-dart-5h95</link>
      <guid>https://forem.com/a_greynoon/asynchronous-synchronous-programming-in-dart-5h95</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Previously in the last &lt;a href="https://dev.to/a_greynoon/single-and-multi-threaded-programming-with-concurrency-and-parallelism-explain-the-differences-and-concepts-3eec"&gt;article&lt;/a&gt;, we talked about the fundamental concepts of single and multi-threaded programming, and understanding how they relate to concurrency and parallelism. Single-threaded programs execute tasks sequentially, one at a time, while multi-threaded programs can handle multiple tasks concurrently or in parallel, depending on the system's capabilities. Also, we talked about how single-threaded programming has the ability to handle multiple tasks at once using the concurrency concept only by switching between tasks, giving each task a small slice of time to execute before moving on to the next task, and can't do parallelism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now, let's talk about synchronous &amp;amp; asynchronous programming concepts and differences in Dart to understand how it deals with tasks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnv3ledqlkozqbiylu8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnv3ledqlkozqbiylu8c.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Synchronous Programming
&lt;/h2&gt;

&lt;p&gt;As we said previously, Synchronous programming means that code is executed sequentially from top to bottom, each statement is completed before the next one begins.&lt;/p&gt;

&lt;p&gt;Synchronous code is often more straightforward to read, predictable, and easy to understand. But because the operations execute sequentially, one by one, it blocks the main thread, leading to unresponsiveness in the user interface, especially for time-consuming tasks like network requests or file operations. Also, CPU cycles are wasted during blocking operations as the application cannot perform other tasks while waiting for the current one to complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Asynchronous Programming
&lt;/h2&gt;

&lt;p&gt;Asynchronous programming allows multiple operations to execute independently without blocking each other, which means that the statements do not have to wait for other operations to finish before they can run.&lt;/p&gt;

&lt;p&gt;Asynchronous code allows the main thread to remain responsive, ensuring a smooth user experience even during time-consuming tasks, and also improving the overall efficiency of the application, as other tasks can continue while waiting for asynchronous operations to be completed. But the code introduces a level of complexity, especially for developers who are new to the paradigm, also debugging code can be more complex.&lt;/p&gt;

&lt;p&gt;Overall, asynchronous programming is a powerful tool that can significantly enhance an application's performance and user experience.&lt;/p&gt;

&lt;h1&gt;
  
  
  What about Dart?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy4ryji2uptxnqfkty2ym.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy4ryji2uptxnqfkty2ym.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dart is a single-threaded system, which means that tasks are executed sequentially, blocking the main thread until each operation completes. It does not support multi-threading which makes it inherently non-concurrent and non-parallel, because there's only one sequence of operations in a single-threaded environment.&lt;/p&gt;

&lt;p&gt;Let's see a simple example of a synchronous program:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

void main() {
   print(1);
   print(2);
   print(3);
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

1
2
3


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this program, the &lt;code&gt;main()&lt;/code&gt; function runs line by line from top to bottom until it completes. This program runs synchronously because it never displays the number 2 before 1 for example.&lt;/p&gt;

&lt;p&gt;For more understanding, let's talk another example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import 'dart:io';

void synchronousOperation() {
  for (int i = 1; i &amp;lt;= 3; i++) {
    print(i);
    sleep(Duration(seconds: 1));
  }
}

void main() {
  print("Start");
  synchronousOperation();
  print("End");
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Start
1
2
3
End


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this example, “Start” is printed, followed by numbers 1 to 3, each with a one-second delay, and finally, “End” is printed. Notice that during the delay, &lt;strong&gt;&lt;em&gt;the entire application is unresponsive.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Sleep Function:&lt;/strong&gt; refers to a synchronous operation that pauses code execution for a specified duration, perhaps to wait for some external process to complete or simply to delay execution, But during that time the entire program will stop. The way of using it is by passing the &lt;code&gt;Duration&lt;/code&gt; object into the &lt;code&gt;Sleep&lt;/code&gt; function when you call it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So... what if there's a time-consuming task, like for example waiting for a file to load or fetching data from a remote server... how can Dart deal with that?&lt;/p&gt;

&lt;p&gt;Well, actually it can by using asynchronous programming. Dart allows us to do asynchronous programming which runs our program without getting blocked, also concurrency can be achieved using &lt;strong&gt;isolates&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But before going any further, let's understand how Dart manages events and what are the isolates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concept of Isolates in Dart
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6hk9rs2krtehgq2f9r9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6hk9rs2krtehgq2f9r9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We know that most platforms have Multi-threaded systems, which allow true parallel execution of tasks, and to take advantage of that, developers traditionally use &lt;strong&gt;shared-memory threads&lt;/strong&gt; running concurrently. However, shared-state concurrency is error-prone and can lead to complicated code.&lt;/p&gt;

&lt;p&gt;Unlike other programming languages, Dart is a single-threaded system and it can approach parallelism and concurrency in different ways by using isolates.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An &lt;strong&gt;isolate&lt;/strong&gt; is an independent execution context that has its own memory and a single thread of execution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, instead of shared-memory threads, Dart code runs inside of isolates, which each isolate has its own memory to ensure that no isolate’s state is accessible from any other isolate, but they communicate by passing messages ensuring clear and controlled data exchange.&lt;/p&gt;

&lt;p&gt;Isolates are Dart's way of achieving concurrency without shared memory, avoiding the complexities and potential issues of traditional multi-threading, and since Isolates run independently they can execute code in parallel, taking full advantage of multi-core processors. This is how Dart achieves true parallelism.&lt;/p&gt;

&lt;p&gt;All Dart code runs in isolates, starting in the default main isolate, and optionally expanding to whatever subsequent isolates you explicitly create. When you spawn a new isolate, it has its own isolated memory and its own event loop. The event loop is what makes asynchronous and concurrent programming possible in Dart.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd41su7pvi23vz164cwgc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd41su7pvi23vz164cwgc.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All code execution begins in what is known as the &lt;strong&gt;default main isolate&lt;/strong&gt;, which is automatically created when the Dart application starts. The main isolate has its own memory space, and event loop, and can handle tasks such as I/O operations, user input, and updates to the UI (in the context of Flutter).&lt;/p&gt;

&lt;p&gt;If the application requires concurrency execution that should run separately from the main isolate or a parallel execution to fully utilize multi-core processors, then you can create a new isolate by 'spawn' it.&lt;/p&gt;

&lt;p&gt;As we mentioned previously, each isolate has its own memory, event loop, and tasks, also they communicate with each other by passing messages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import 'dart:isolate';


void sayhii(var msg) {
  print('execution from sayhii ... the message is :${msg}');
}

void main() { 
  Isolate.spawn(sayhii, 'Hello!!');
  Isolate.spawn(sayhii, 'Whats up!!');
  Isolate.spawn(sayhii, 'Welcome!!');

  print('execution from main1');
  print('execution from main2');
  print('execution from main3');
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;output:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

execution from sayhii ... the message is :Hello!!

execution from main1

execution from main2

execution from main3

execution from sayhii ... the message is :Welcome!!

execution from sayhii ... the message is :Whats up!!

Exited.


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this example, we have two functions &lt;code&gt;sayhii()&lt;/code&gt; and &lt;code&gt;main()&lt;/code&gt; function might not run in the same order each time cause the &lt;code&gt;Isolate.spawn&lt;/code&gt; method creates a new isolate for the function &lt;code&gt;sayhii&lt;/code&gt;, and executed it in parallel with the remaining code. If you run the code again, the output will be different each time as we can see in the second output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Another example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import 'dart:isolate';

void isolateFunction(SendPort sendPort) {
  sendPort.send('Message from the new isolate');
}

void main() async {
  ReceivePort receivePort = ReceivePort();
  await Isolate.spawn(isolateFunction, receivePort.sendPort);
  receivePort.listen((message) {
    print('Main isolate received: $message');
  });
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;output:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Main isolate received: Message from the new isolate


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As we saw, isolates do not share memory, so they communicate with each other by passing messages using &lt;code&gt;SendPort&lt;/code&gt; and &lt;code&gt;ReceivePort&lt;/code&gt;. The main isolate can send data to the new isolate via a &lt;code&gt;SendPort&lt;/code&gt;, and the new isolate can reply using another &lt;code&gt;SendPort&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But what is the Event loop, and what is the deal with &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt;?&lt;br&gt;
&lt;strong&gt;Don't worry I will explain each one.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Event loop
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4r9u4zjojaqld6giuscs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4r9u4zjojaqld6giuscs.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we said earlier, All the code you write within the &lt;code&gt;main()&lt;/code&gt; function and any synchronous or asynchronous operations that do not involve other isolates are executed in the main isolate.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Event:&lt;/strong&gt; refers to a unit of work or a task that is scheduled to be processed by the event loop, it can be anything from server requests to repaint the UI, to user taps and keystrokes, to I/O from the disk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Event loop:&lt;/strong&gt; refers to an invisible process that manages the execution of events and callbacks. Dart’s runtime model is based on an event loop, which is responsible for executing the program's code,  processing scheduled events, and more.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  How Does Event Loop Work?
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cre42hzc3g8988ni3bl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cre42hzc3g8988ni3bl.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Dart event loop main job is to handle events, like mouse taps, buttons tap, or request data from a remote server. And it works by continuously checking two queues:-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Micro-task queue.&lt;/li&gt;
&lt;li&gt;Event queue. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The micro-task queue is used for &lt;strong&gt;short asynchronous internal actions&lt;/strong&gt; that come from your Dart code like for example long-running tasks, and it is what the event loop considers first ensuring that all pending micro-tasks are completed before moving on to the next event in the event queue.&lt;/p&gt;

&lt;p&gt;The event queue is used for handling &lt;strong&gt;asynchronous external events&lt;/strong&gt; such as I/O operations, timers, user interactions, and messages between isolates.&lt;/p&gt;

&lt;p&gt;The micro-task queue is ideal for tasks that you want to have completed as soon as possible, but not immediately. For instance, you might use the micro-task queue to delay some computation or to allow the UI to update between tasks.&lt;/p&gt;

&lt;p&gt;This priority system allows Dart to handle smaller, internal tasks immediately while deferring larger or external tasks until the micro-tasks are complete, maintaining efficiency and responsiveness in asynchronous operations.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember: both the &lt;strong&gt;micro-task queue&lt;/strong&gt; and the &lt;strong&gt;event queue&lt;/strong&gt; are parts of Dart's &lt;strong&gt;asynchronous programming&lt;/strong&gt; model, and they are designed to manage asynchronous operations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The event loop is always running. It continuously checks the synchronous tasks, micro-task queue, and event queue. So, when the Flutter application runs :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The main isolate is created and the event loop starts, The &lt;code&gt;void main()&lt;/code&gt; is the first to execute synchronously.&lt;/li&gt;
&lt;li&gt;It always runs synchronous tasks immediately, but that doesn't mean it can't be possible to interrupt them.&lt;/li&gt;
&lt;li&gt;If all the tasks in the main isolate are completed, the event loop moves the tasks (if available) from the micro-task queue to the main isolate for execution until the micro-task queue is empty.&lt;/li&gt;
&lt;li&gt;If both synchronous tasks and the micro-task queue are empty, the event loop moves the tasks from the event queue to the main thread for execution.&lt;/li&gt;
&lt;li&gt;The event loop continues until all the queues are empty.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5o9e3e0aagkd824lbbmp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5o9e3e0aagkd824lbbmp.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's also an animated &lt;strong&gt;youtube&lt;/strong&gt; diagram for the event loop lifecycle:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=OLAXR0TCrcc" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fueyvubf31sjks4r829zq.jpg" alt="Animated Dart Event Loops"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Asynchronous programming in Dart involves the use of &lt;code&gt;Future&lt;/code&gt; objects and &lt;code&gt;async&lt;/code&gt; functions (we will explain it later). Whenever we write asynchronous code we schedule tasks to be run later. For example, when we use &lt;code&gt;Future&lt;/code&gt; objects and &lt;code&gt;async&lt;/code&gt; functions, we’re telling the Dart event loop to complete other Dart codes first and come back when the Future is complete.&lt;/p&gt;

&lt;p&gt;Here is a simple example of how the Dart event loop works:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import 'dart:async';


void main() {
  print('Dart app starts');
  Future(() =&amp;gt; print('This is a new Future'));
  scheduleMicrotask(() =&amp;gt; print('This is a micro task'));
  print('Dart app ends');
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Dart app starts
Dart app ends
This is a micro task
This is a new Future


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;main&lt;/strong&gt; function executes synchronously. The &lt;code&gt;print(‘Dart app starts’)&lt;/code&gt; and &lt;code&gt;print(‘Dart app ends’)&lt;/code&gt; are executed immediately. The &lt;code&gt;Future&lt;/code&gt; and &lt;code&gt;scheduleMicrotask&lt;/code&gt; calls are added to their respective queues and are executed once the &lt;strong&gt;main&lt;/strong&gt; function has completed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Another example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import 'dart:async';

void main() {
  print('Dart app starts');
  scheduleMicrotask(() =&amp;gt; print('Microtask 1'));
  scheduleMicrotask(() =&amp;gt; print('Microtask 2'));
  Future(() =&amp;gt; print('This is a new Future'));
  print('Dart app ends');
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Dart app starts
Dart app ends
Microtask 1
Microtask 2
This is a new Future


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this sample code, &lt;code&gt;scheduleMicrotask&lt;/code&gt; functions are processed before the new Future, although the &lt;code&gt;Future&lt;/code&gt; was added to the event queue before &lt;code&gt;scheduleMicrotask&lt;/code&gt; was added to the micro-task queue. This demonstrates how Dart prioritizes micro-tasks over events.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now we know everything about &lt;strong&gt;synchronous programming&lt;/strong&gt; and &lt;strong&gt;asynchronous programming&lt;/strong&gt; models, synchronous code is executed sequentially blocking the main thread until each operation completes, while asynchronous code allows tasks to run independently without blocking which keeps the main thread responsive and improves overall performance.&lt;/p&gt;

&lt;p&gt;Dart is a single-threaded system and it handles operations concurrency through &lt;strong&gt;isolates&lt;/strong&gt;. Isolates provide a way to achieve concurrency and parallelism by running in separate memory spaces and communicating via message-passing, avoiding the pitfalls of shared memory.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;event loop&lt;/strong&gt; in Dart manages both synchronous and asynchronous tasks using &lt;strong&gt;micro-task&lt;/strong&gt; and &lt;strong&gt;event queues&lt;/strong&gt;, ensuring smooth task execution and responsiveness.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;By understanding these foundational concepts, now we know how to implement synchronous code in Dart... but what about asynchronous code?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Well, in the next article, we will dive into how to implement it in Dart cause this is already a long one and that is enough.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thank you for your time and I will see you in the next one.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>mobiledevelopment</category>
      <category>programming</category>
    </item>
    <item>
      <title>Single and Multi-Threaded Programming with Concurrency and Parallelism - Explain The Differences and Concepts</title>
      <dc:creator>Ahmed_Greynoon</dc:creator>
      <pubDate>Thu, 29 Aug 2024 07:57:12 +0000</pubDate>
      <link>https://forem.com/a_greynoon/single-and-multi-threaded-programming-with-concurrency-and-parallelism-explain-the-differences-and-concepts-3eec</link>
      <guid>https://forem.com/a_greynoon/single-and-multi-threaded-programming-with-concurrency-and-parallelism-explain-the-differences-and-concepts-3eec</guid>
      <description>&lt;p&gt;In the world of programming, you definitely will face the concepts of single and multi-threaded programming, these concepts are closely tied to how a programming language handles concurrent execution and parallelism. In this article, we will explore the concepts and differences between them.  But first, we need to understand concurrency and parallelism.&lt;/p&gt;

&lt;p&gt;Also... why should we know about this? 🤔 why would we bother ourselves to learn this? 🤔&lt;br&gt;
trust me, I'm cooking something 👨🏻‍🍳🔥 and everything is connected so be patient and read. 🤗 &lt;/p&gt;

&lt;h2&gt;
  
  
  Concurrency Vs Parallelism
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxzdlbnvhcjv3x7cvrwc9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxzdlbnvhcjv3x7cvrwc9.png" alt="Image description" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Concurrency:&lt;/strong&gt; refers to the ability of a system to handle multiple tasks at once. However, this doesn't mean that the tasks are literally being executed simultaneously (at the exact same moment). Instead, concurrency allows multiple tasks to make progress during overlapping time periods. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parallelism:&lt;/strong&gt; occurs when two or more tasks run at the same time (simultaneously). They start, run, and complete in parallel, for example in your PC when your processor has more than one core, it is capable of running multiple threads at the same time. Each processor core can be working on a different task. This is a form of parallelism.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a single-core processor, for example, it can only execute one instruction at a time. However, the operating system can rapidly switch between tasks, giving each task a small slice of time to execute before moving on to the next task. So, even though the processor is only executing one task at any given moment, it switches between tasks so quickly that it appears as though they are happening concurrently.&lt;/p&gt;

&lt;p&gt;In multi-core processors also, for example, true parallelism can occur where different cores handle different tasks simultaneously. However, concurrency still applies because even within a single task, the system may break it down into smaller sub-tasks that are managed concurrently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy2d3rpr9u33p5zrvrxe2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy2d3rpr9u33p5zrvrxe2.jpg" alt="Image description" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Single and Multi-Threaded Programming
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh68e994yuiu8pr14h7lk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh68e994yuiu8pr14h7lk.png" alt="Image description" width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Single-Threaded Programming
&lt;/h3&gt;

&lt;p&gt;In single-threaded programming, a program operates on a single thread of execution. This means that the program executes one task at a time in a sequential manner, which means that a program follows the order of operations as defined in the code, executing one operation at a time. But if it encounters a time-consuming task (like for example waiting for a file to load or fetching data from a remote server), it must finish this task before moving on to the next. &lt;/p&gt;

&lt;p&gt;This is inherently non-concurrent and non-parallel cause there's only one sequence of operations and in a single-threaded environment, there is no true concurrency because if tasks appear to run simultaneously they are actually being interleaved or managed through time-slicing, in which the opposite of what we said previously "The Concurrency refers to the ability of a system to handle multiple tasks at once", which creates the illusion of concurrency.&lt;/p&gt;

&lt;p&gt;But for Parallelism, a Single-threaded environment cannot achieve true parallelism because there’s only one thread doing all the work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Threaded Programming
&lt;/h3&gt;

&lt;p&gt;In multi-threaded programming, a program runs multiple threads concurrently. These threads can perform different tasks simultaneously or handle multiple parts of a single task.&lt;/p&gt;

&lt;p&gt;A multi-threaded program can split tasks into multiple threads, which can be run either concurrently or in parallel depending on the system's capabilities and the nature of the tasks.&lt;/p&gt;

&lt;p&gt;In a multi-threaded environment, concurrency is achieved by allowing multiple threads to make progress on different tasks or parts of the same task. Concurrency doesn't necessarily mean that these tasks are being executed at the same time; it just means that they are being managed in such a way that it seems like they are happening simultaneously.&lt;/p&gt;

&lt;p&gt;Parallelism occurs in a multi-threaded environment when multiple threads actually run at the same time on different cores of a multi-core processor. This is true parallel execution, where tasks are processed simultaneously, leading to potentially significant performance improvements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fap1wkuy893khlkg18pkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fap1wkuy893khlkg18pkt.png" alt="Image description" width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now, we understand the difference between &lt;strong&gt;concurrency&lt;/strong&gt; and &lt;strong&gt;parallelism&lt;/strong&gt;, &lt;strong&gt;Concurrency&lt;/strong&gt; is managing multiple tasks that execute during overlapping periods which is often achieved on single-core processors, while parallelism is about executing multiple tasks at the same time which is possible on multi-core processors.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;single-threaded programming&lt;/strong&gt;, tasks run sequentially without true concurrency or parallelism, but &lt;strong&gt;multi-threaded programming&lt;/strong&gt; can run concurrently or in parallel improving performance by handling multiple tasks more efficiently.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Next article, we will learn more about these concepts and theories, and how to implement them using Dart programming language, and now I bet you know why 😁😁&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Thank you for your time 🥰🥰
&lt;/h3&gt;

&lt;h3&gt;
  
  
  I hope this article has made things clear to you.
&lt;/h3&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>programming</category>
      <category>mobiledevelopment</category>
    </item>
  </channel>
</rss>
