DART异步/等待不等待

时间:2017-07-07 02:03:55

标签: asynchronous async-await dart

所以我一直在尝试使用DART(我的核心语言是C ++和嵌入式C派生)。因此,我的代码可能并不漂亮,因为我更像是一个程序员程序员,但我已经过去并且学习......我一直在围绕等待同步的期货挣扎,基本上,我根本无法让DART等待。以下代码建立与小型嵌入式设备的套接字连接并提取信息。这一切都有效,但注意操作的顺序应该是main()从控制台获取一些信息,然后应该调用方法cardStatus运行并通过套接字连接从嵌入式设备获取信息。这是等待应该发生的地方。当返回Future时,它应该转到printstuff()方法。我已经添加了应该按顺序排列的打印语句并阅读:

  • 这应该打印第1个
  • 这应该打印第二个
  • 这应该打印第3次

相反,因为在cardstatus调用上没有发生等待(这非常耗时),我得到:

  • 这应该打印第1个
  • 这应该打印第3次
  • 这应该打印第二个

我已经关注了使用async的另一个主题,并且似乎至少遵循了使用此Other thread的一种可靠方式(我尝试了一个带有类似结果的完成符的.then,所以有一些核心,我觉得我失踪了)..但我已经坚持了一个星期。

下面的代码,以及控制台输出。

import 'dart:io';
import 'dart:async' show Future;

const String STATUS = "#111111;";

String defaultIP = "10.1.14.202";
int defaultConfigPort = 5111;
int defaultControlPort = 6722;

var card = new Map();

getInput(String defaults) {
  String takenin = stdin.readLineSync();
  if (takenin == '') takenin = defaults;
  return takenin;
}

Future main() async {
  stdout.write('What is the IP address of the card ($defaultIP): ');
  String ipaddress = getInput(defaultIP);
  defaultIP = ipaddress;
  print ("This should print 1st");
  stdout.writeln("Connecting to $defaultIP");
  await cardStatus(defaultIP, defaultConfigPort, STATUS, card);
  printstuff();
}

printstuff() {
  stdout.writeln(card['subnet']);
  print ("This should print 3rd");
}
Future cardStatus(String ip, int port, String message, Map card) {
  return new Future.delayed(Duration.ZERO, () {
    Socket.connect(ip, port).then((socket) {
      print('Connected to: '
          '${socket.remoteAddress.address}:${socket.remotePort}');

      socket.listen((data) {
        print(new String.fromCharCodes(data).trim());
        List str1 = (new String.fromCharCodes(data).trim().split(','));
        print(str1);
        print ("This should print 2nd");
        //var card = new Map();
        card['ip'] = str1[0];
        card['subnet'] = str1[1];
        card['gateway'] = str1[2];
        card['unknown'] = str1[3];
        card['persist'] = str1[4] == 'true';
        card['build'] = str1[5];
        card['serial'] = str1[6].substring(0, 14);
        card['cloudpassword'] = str1[6].substring(14, 20);
        card['DNS'] = str1[7];
        card['cloudhost'] = str1[8];
        card['cloudenabled'] = str1[9] == 'true';
        print(card['ip']);
      },
          onDone: () {
            print("Done");
            socket.destroy();
          });

//Send the request
      socket.write(message);
    });
  });
}

这是当前的控制台输出。请注意,如果cardStatus已经完成,则null不应为null,将打印为str1。

What is the IP address of the card (10.1.14.202): 
This should print 1st
Connecting to 10.1.14.202
null
This should print 3rd
Connected to: 10.1.14.202:5111
>10.1.14.202,255.255.255.0,10.1.14.1,,0,435,F44900A60040F8000000,192.168.1.1,connect.tutuuu.com,0;
[>10.1.14.202, 255.255.255.0, 10.1.14.1, , 0, 435, F44900A60040F8000000, 192.168.1.1, connect.tutuuu.com, 0;]
This should print 2nd
10.1.14.202
Done

Process finished with exit code 0

感谢您的帮助!

2 个答案:

答案 0 :(得分:4)

return之前您遗失了Socket.connect。现在,您的代码刚刚开始连接,但从未等待它。我强烈建议尽可能多地使用新的await / async语法。

以下是一个获取google主页的正在运行的示例:

import 'dart:io';
import 'dart:async' show Future;

Future main() async {
  print("This should print 1st");
  await cardStatus('www.google.com', 80, 'GET /\nHTTP 1.1\n\n');
  printstuff();
}

printstuff() {
  print("This should print 3rd");
}

Future cardStatus(String ip, int port, String message) {
  return new Future.delayed(Duration.ZERO, () {
    return Socket.connect(ip, port).then((socket) {
      print('Connected to: '
          '${socket.remoteAddress.address}:${socket.remotePort}');

      socket.listen((data) {
        List str1 = (new String.fromCharCodes(data).trim().split(','));
        print(str1.first);
        print("This should print 2nd");
      }, onDone: () {
        print("Done");
        socket.destroy();
      }, onError: (e) {
        print("Error while listening: $e");
      });
      socket.write(message);
    });
  });
}

使用等待的稍微编辑的版本,并尝试使用/ catch来处理错误:

import 'dart:io';
import 'dart:async' show Future;

Future main() async {
  print("This should print 1st");
  await cardStatus('www.google.com', 80, 'GET /\nHTTP 1.1\n\n');
  print("This should print 3rd");
}

Future<String> cardStatus(String ip, int port, String message) async {
  var socket = await Socket.connect(ip, port);
  print('Connected to: '
      '${socket.remoteAddress.address}:${socket.remotePort}');
  socket.write(message);
  print("Sent request");
  try {
    var response = await socket.fold(
        '',
        (String acc, List<int> data) =>
            acc + new String.fromCharCodes(data).trim());
    print("Received response: ${response.substring(0, 10)}");
    return response;
  } finally {
    socket.close();
  }
}

答案 1 :(得分:0)

我知道回答了这个问题,但是问题很严重,我对这个概念感到困惑,因此这是另一个让我理解的元素。在dartpad(https://dartpad.dartlang.org/)中尝试此操作(注释在代码中):

import 'dart:async';

//Just creating a duration to use later
Duration duration = new Duration(milliseconds: 500);

void main() {
  //This is what tricked me, printStuff is async so running in parallel processing by default
  //There is no need to call the function in a certain way (like a go xxx for a goroutine)
  //there is an await in the function so it will wait inside the function only 
  //i.e. printStuff('a') starts then printStuff('b') starts straight away...already in prallel processing
  //Run it and check the output 
  printStuff('a');
  printStuff('b');
  //Basically the await is in the function so printStuff is still returning a Future
  //i.e. printStuff('a') starts but doesn't wait to complete to start printStuff('b')   
}
Future<void> printStuff(String id) async {
  for(int i = 0; i <= 5; ++i) {
    //this await is waiting for the command to complete to move to the next iteration...
    //the i iterations are done one after the other
    await new Future.delayed(duration, () {
      print(id + i.toString()); 
    });   
  }    
}

然后尝试:

import 'dart:async';

Duration duration = new Duration(milliseconds: 500);

//becuase I use await in main now, I must make it return a future and be async
Future main() async {
  //to make it happen one after the other, you need await at a call function level
  await printStuff('a');
  await printStuff('b');
  //Basically this says complete printStuff('a'), then start printStuff('b')...
  //and yes technically one doesn't need the second await becuase there is nothing after
}

Future<void> printStuff(String id) async {
  for(int i = 0; i <= 5; ++i) {
    await new Future.delayed(duration, () {
      print(id + i.toString());
    });
  }
}

所以我个人的误解是异步函数立即被并行调用,而函数中的await则等待真实的但函数本身,而不会影响其他并行处理。