9

I know Dart is Single Threaded, flutter is also, so if I do some heavy task, it will block the UI event queue, but a network request takes several seconds without blocking the UI.

so, why Socket does not block UI? What bothers me is why the socket does not block the UI, but the heavy task does, Although they all asynchronous task.

for example, this code will block UI

@override
void initState() {
super.initState();
Future((){
  var result;
  for (var i = 0; i < 1000000; ++i) {
    result = 'result is $i';
  }
  print(result);
});

this code is normal HTTP request,it won't block UI

get() async {
  var httpClient = new HttpClient();
  var uri = new Uri.http(
      'example.com', '/path1/path2', {'param1': '42', 'param2': 'foo'});
  var request = await httpClient.getUrl(uri);
  var response = await request.close();
  var responseBody = await response.transform(UTF8.decoder).join();
}

The reason why the socket does not block the UI is to split the request process into multiple parts? and send these part to the current microtask queue,As this answer says:

https://stackoverflow.com/a/56783713/6540631

so, does anyone know how sockets are implemented asynchronously? Whether socket use Isolate, Future, or other means?The socket run on UI thread, or other thread?

and, If I have to perform heavy tasks that cannot be split in the UI thread(such as text layout), what should I do?


Supplementary explanation:

I know how to use Future and Isolate, but I encountered a problem.

if use TextPainter.layout in isolate will get a compiler error native function not found.

I need layout many words and it takes a long time (100ms+), it will block UI thread.

What should I do?

https://github.com/flutter/flutter/issues/30604

The Flutter engine native APIs for the UI package is only available in the primary isolate.

https://github.com/flutter/flutter/issues/30604#issuecomment-481380706

right now you would have to write your own line-breaking logic - perhaps as a plugin. We don't currently have any API for doing text layout in a separate isolate. @GaryQian might have some other idea about this too.

https://github.com/flutter/flutter/issues/30604#issuecomment-526013977

so I have to do text layout in UI thread(use TextPainter ), although write a plugin can solve this problem and it work well, Is there an easier way?

I guess I can get help from the implementation details of the socket, so I raised this question.

Hamed
  • 5,867
  • 4
  • 32
  • 56
Lucky Dog
  • 608
  • 5
  • 15
  • I know neither flutter nor dart, but I believe the documentation explains the concept of asynchronous task really well: https://dart.dev/codelabs/async-await#uncompleted – ph3rin Sep 30 '19 at 04:16
  • 1
    1. Single-threaded does not mean that everything is blocking. Work can still be done asynchronously (you might want to read up on [coroutines](https://en.wikipedia.org/wiki/Coroutine)). 2. Each *isolate* in Dart is single-threaded, but Dart supports having multiple isolates. 3. Flutter has a single UI isolate, but the Flutter *engine* uses multiple threads for various things. – jamesdlin Sep 30 '19 at 04:32
  • @Kaenbyou Rin but why the heavy task will block UI,the network request doesn't,Although they all use asynchronous task – Lucky Dog Sep 30 '19 at 04:59
  • @jamesdlin Does socket use Isolate? What bothers me is why the socket does not block the UI,but the heavy task does,Although they all asynchronous task – Lucky Dog Sep 30 '19 at 05:05
  • @LuckyDog Provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) please. Show us the code that is blocking the thread. – ph3rin Sep 30 '19 at 05:07
  • @Kaenbyou Rin OK,Already done – Lucky Dog Sep 30 '19 at 05:12
  • @LuckyDog Well according to the SO link you posted: "function must yield (usually via `await`) to allow other operations to execute in the isolate." If you don't yield, it will block the UI thread. – ph3rin Sep 30 '19 at 05:23
  • @Kaenbyou Rin But I have used Future,it also block UI, I know the heavy task must run on Isolate,but why?and why doesn't the socket need this? – Lucky Dog Sep 30 '19 at 05:29
  • There is a lot of similar `async` and `isolate` discussion in SO, [here](https://stackoverflow.com/questions/52498773/flutter-isolate-vs-future) is one of them. – Tokenyet Sep 30 '19 at 05:29
  • @Tokenyet so does socket use Isolate?I want to know why the socket won't block UI – Lucky Dog Sep 30 '19 at 05:35
  • @LuckyDog You used a `Future`, but your `Future`'s *entire* computation happens synchronously when that `Future` executes. It doesn't do part of its computation and defer the rest (yielding). The answer you linked to already shows how to avoid blocking. – jamesdlin Sep 30 '19 at 05:39
  • 3
    @LuckyDog Whether socket use Isolate is implementation detail. It might have started a thread and wait on synchronous I/O requests, or it could have used system native asynchronous I/O APIs (`IOCP` on Windows or `epoll` on linux). – ph3rin Sep 30 '19 at 05:40
  • @LuckyDog As for sockets, I haven't looked at the implementation, but I would guess that they're implemented in the VM/runtime on a separate thread. But as mentioned, it's an implementation detail that you shouldn't need to be concerned with. – jamesdlin Sep 30 '19 at 05:40
  • If you really want to know the answer that It's about source code instead of coding, try to find the [source code](https://github.com/flutter/flutter). – Tokenyet Sep 30 '19 at 05:44
  • @Kaenbyou Rin This is exactly what I guess. I guess the socket run on the IO Thread,and it is created and managed by IO Task Runner,but this is just a guess,I want to know if it is as we guessed – Lucky Dog Sep 30 '19 at 05:58
  • @Kaenbyou Rin I also want to know how to run custom task on IO thread,although The official documentation says that the current user code cannot get the IO Task Runner in any way.maybe someone knows – Lucky Dog Sep 30 '19 at 06:04

1 Answers1

7

In dart, Network calls are asnycronous nature and returns Future. When anything is asynchronous, it runs in the background and returns result or response on task completion. It's quite similar to Promise in javascript. Here are list of key terms related to Async in dart taken from Official Docs.

Key terms:


synchronous operation: A synchronous operation blocks other operations from executing until it completes.
synchronous function: A synchronous function only performs synchronous operations.
asynchronous operation: Once initiated, an asynchronous operation allows other operations to execute before it completes.
asynchronous function: An asynchronous function performs at least one asynchronous operation and can also perform synchronous operations.

In your case, you have used Future but function must yield via await to allow other operations to execute in the isolate. If you don't yield, it will block the UI thread. That's exactly you got in the first code block and UI gone blocked. You have used Future but the computation still goes synchronous in it. There is a precise Post here for more reference.
Martin Westin
  • 1,419
  • 1
  • 14
  • 25
Kiran Maniya
  • 8,453
  • 9
  • 58
  • 81
  • 2
    Why doesn't the socket block the UI? This is where I am confused. – Lucky Dog Sep 30 '19 at 07:19
  • 1
    the socket is also a network and that's why it's isolated. please refer to the docs of socket library you are consuming and comment if you still confused with it. – Kiran Maniya Sep 30 '19 at 07:34
  • 2
    But on Android (before 4.0), Socket blocks the UI.so I guess Socket isn't isolated,but the Flutter system isolates the socket. – Lucky Dog Sep 30 '19 at 07:51