“This is the 25th day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”

In previous articles, we have studied the use of Future asynchronous programming and Isolate multi-threading. Today we will take a look at how to use asynchronous programming with multi-threading.

Asynchrony is used in combination with multithreading

Let’s start with a piece of code:

void main() {
  testIsoLoad();
}

void testIsoLoad() {
  Future(() => compute(func, 123)).then((value) => print('1'));
  Future(() => compute(func, 123)).then((value) => print('2'));
  Future(() => compute(func, 123)).then((value) => print('3'));
  Future(() => compute(func, 123)).then((value) => print('4'));
  Future(() => compute(func, 123)).then((value) => print('5'));
}

func(int message) {}
Copy the code

Run the project and view the printed result:

From the print result, we can draw the conclusion that these several print operations are asynchronous, they are processed in the child thread;

However, according to our previous research on Future, multiple futures should be synchronous, so why is it asynchronous here? Next, we modify the code in the testIsoLoad method, leaving the rest of the code unchanged, as follows:

Then, we run the project and see the print:

Warning us to run the project several times and finally find the print order is 1, 2, 3, 4, 5, so why is this? How did it become synchronous again? We just called the => method instead of {}, how does the code execute differently?

Compute (func, 123) => compute(func, 123) => compute(func, 123) => compute(func, 123) => compute(func, 123) Modify the testIsoLoad method as follows:

The running results are as follows:

After several runs, the result is not fixed, that is, after we perform the return operation, the synchronous execution process becomes asynchronous, which also verifies the above mentioned => function call method will return the result;

If the child thread’s Future is returned in the Future(compute encapsulates the Future), then the child thread’s asynchronous task is processed. Now that THEN is an asynchronous operation of a child thread, what about tasks in the Future?

We added the following print to the Future:

Running results;

As you can see, while THEN handles asynchronous tasks for child threads, the Future still has synchronous tasks;

Future and microtasks

Let’s look at the following code:

  Future f = Future(() {
    print('Asynchronous Task 1');
    scheduleMicrotask(() {
      print('Microtask 1');
    });
  });
Copy the code

It is obvious that we can all perform the result: asynchronous tasks execute first, then micro-tasks;

What if we continue to add a then method to f?

  Future f = Future(() {
    print('Asynchronous Task 1');
    scheduleMicrotask(() {
      print('Microtask 1');
    });
  });
  f.then((value) {
    print('Micromission 2');
  });
Copy the code

What is the result of this execution?

The result is that microtask 2 is executed before microtask 1. This is because the THEN method can be regarded as an integral part of the Future task. That is, the THEN method (a microtask) is added to the queue first, and the microtask of microtask 1 is added to the THEN method, so the THEN method is executed first.

Not only that, we add a whenComplete method to see the print:

  Future f = Future(() {
    print('Asynchronous Task 1');
    scheduleMicrotask(() {
      print('Microtask 1');
    });
  });
  f.whenComplete(() {
    print('complete');
  });
  f.then((value) {
    print('Micromission 2');
  });
Copy the code

The print result is as follows:

WhenComplete can also be considered as an integral part of the Future task. WhenComplete and then are executed in order of addition.

Asynchronous and multithreaded options

So when do you use asynchronous tasks and when do you use multithreading?

Although the Future is an asynchronous task, time-consuming operations in the Future block the main thread. Look at the following code:

We added a for loop to the camera button click method to simulate time-consuming operation. As you can see from the print result, when the time-consuming operation in the Future starts to execute, the interface is blocked and cannot slide! When the time-consuming operation is over, the sliding operation can be carried out;

At this point, we can use compute:

Putting time-consuming operations in methods of compute does not block the main thread. Compute can be used instead of the Future.