Asynchronous 如何使异步Dart调用同步?

Asynchronous 如何使异步Dart调用同步?,asynchronous,dart,synchronous,Asynchronous,Dart,Synchronous,我正在为一家德国公司评估Dart,方法是将各种Java程序移植到Dart,并对结果进行比较和分析。在浏览器中,Dart可以轻松获胜。对于服务器软件来说,性能似乎是一个严重的问题(请参阅),但这基本上被化解了 现在,我正在移植一些“简单”的命令行工具,我没有想到会有任何严重的问题,但至少有一个。有些工具确实发出HTTP请求以收集某些数据,而独立Dart虚拟机仅以异步方式支持这些请求。综观所有我能发现的,在一个主要是同步的软件中使用任何异步调用似乎都是不可能的 我知道我可以将可用的同步软件重组为异步

我正在为一家德国公司评估Dart,方法是将各种Java程序移植到Dart,并对结果进行比较和分析。在浏览器中,Dart可以轻松获胜。对于服务器软件来说,性能似乎是一个严重的问题(请参阅),但这基本上被化解了

现在,我正在移植一些“简单”的命令行工具,我没有想到会有任何严重的问题,但至少有一个。有些工具确实发出HTTP请求以收集某些数据,而独立Dart虚拟机仅以异步方式支持这些请求。综观所有我能发现的,在一个主要是同步的软件中使用任何异步调用似乎都是不可能的

我知道我可以将可用的同步软件重组为异步软件。但这会将设计良好的软件转化为可读性较差、调试和维护难度较大的软件。对于某些软件来说,这根本没有意义。 我的问题:是否有一种(我忽略了)方法可以将异步调用嵌入到同步调用的方法中

我认为,提供一个仅在主线程内可用的系统调用并不困难,它只是将执行转移到整个队列异步函数调用列表中(不必先结束主线程),并且在最后一个被执行时返回并继续主线程

可能是这样的:

Future<bool> save() async {
  // save changes async here
  return true;
}

void saveClicked() {
  saveButton.enabled = false;
  save()
    .then((success) => window.alert(success ? 'Saved' : 'Failed'))
    .catchError((e) => window.alert(e))
    .whenComplete(() { saveButton.enabled = true; });
}
Future<Null> saveClicked() async {
  saveButton.enabled = false;
  try {
    bool success = await save();
    window.alert(success ? 'Saved' : 'Failed');
  }
  catch (e) {
    window.alert(e);
  }
  finally {
    saveButton.enabled = true;
  }
}
var synchFunction(){
var结果;
asyncFunction()。然后((){result=…;});
resync();//移动到并等待所有异步执行的系统调用
返回结果;
}
拥有这样的方法也会简化libapi。大多数“同步”呼叫都可以删除,因为重新同步呼叫可以完成此任务。这似乎是一个如此合乎逻辑的想法,我仍然认为它不知何故存在,但我错过了它。还是有一个严重的原因,为什么这不起作用?
在考虑了两天从
lm
(见下文)收到的答案后,我仍然不明白为什么不可能将异步Dart调用封装到同步Dart调用中。它总是在“正常”的同步编程环境中完成的。通常,您可以通过从异步例程获取“完成”或在超时后继续某个操作失败来等待重新同步

考虑到这一点,我的第一个建议可以这样加强:

var synchFunction(){
var结果;
异步函数()
.然后((){result=…;})
.whenComplete((){continueResync()});//完成消息
重新同步(超时);//以超时作为最大限制进行等待
//我们要么填写[result]到达这里,要么填写[TimeoutException]。
返回结果;
}
resync()
执行与结束隔离的
main
方法后通常发生的相同操作,它开始执行排队的异步函数(或等待事件使其可执行)。一旦遇到
continueResync()
调用,就会设置一个标志来停止此异步执行,并
resync()
返回主线程。如果在给定的
timeout
期间未遇到
continueResync()
调用,它也会中止异步执行,并使用
TimeoutException
离开
resync()

对于某些受益于直接同步编程的软件组(不是客户端软件,也不是服务器软件),这样的功能将为必须处理仅异步库的编程人员解决许多问题


我相信我也为下面的
lm
论证中的主要论点找到了解决方案。因此,对于我提出的这个“增强”解决方案,我的问题仍然存在:是否有任何东西真的使Dart无法实现这一点?Dart本质上是异步的。试图避免异步是行不通的。 有些API调用有同步版本,例如在
dart:io
中,在某些情况下使用它们似乎更简单,但因为没有所有方法/函数的同步版本,所以无法完全避免异步

随着最近推出的
async
/
await
功能,异步编程变得更加简单,代码看起来几乎像同步代码(但事实并非如此)


如果调用变为异步,它将保持异步。据我所知,您对此无能为力。

在Dart的当前执行模型中无法实现
重新同步
功能

异步执行具有传染性。同步函数必须在执行任何其他异步事件之前返回,因此无法同步等待异步执行

Dart中的执行是单线程和基于事件的。
resync
函数无法在不阻止同一隔离中所有其他执行的情况下阻止,因此挂起的异步操作永远不会发生

要阻止同步执行并继续执行其他操作,您需要将整个调用堆栈保留到该点,并在同步操作完成后将其恢复。如果您拥有该功能,那么可能有比Future和Stream更好的方法来做事情:)

此外,在基于事件的系统中,等待“所有异步执行”的定义并不明确。可能有广播流发出来自网络的事件、定期计时器或接收端口从另一个隔离区获取数据、或其他一些您无法等待的事件源,因为它们来自隔离区之外,或事件进程。当当前隔离关闭时,它可能会向另一个隔离发送一条最终关闭消息,因此实际上“异步执行”不会停止
final int number = waitFor<int>(someAsyncThatReturnsInt);

    class StartConversationState extends State<StartConversationStatefulWidget> {

      @override
      Widget build(BuildContext context) {

        _delayPush(); // this is the call that gets triggered multiple times
      }

      int lastKnownTime = 0;
      int delayMillis = 3000;

      _delayPush() async {
        delayMillis += 1500;

        await new Future.delayed(Duration(milliseconds: delayMillis));

        int millisSinceEpoch = new DateTime.now().millisecondsSinceEpoch;
        int delta = millisSinceEpoch - lastKnownTime;

        // if delta is less than 10 seconds, means it was a subsequent interval
        if (delta < 10000) {

          print('_delayPush() , SKIPPING DUPLICATE CALL');
          return;
        }

        // here is the logic you don't want to duplicate
        // eg, insert DB record and navigate to next screen
    }

import 'package:synchronized_lite/synchronized_lite.dart';

import 'dart:async';

// Using Lock as a mixin to further mimic Java-style synchronized blocks
class SomeActivity with Lock {

  bool _started = false;

  Future<bool> start() async {
    // It's correct to return a Future returned by synchronized()
    return synchronized(() async {
      if(_started)
        return false;
      // perform the start operation
      await Future.delayed(Duration(seconds: 1));
      print("Started");
      _started = true;
      return true;
    });
  }

  Future<void> stop() async {
    // It's also correct to await a synchronized() call before returning
    // It's incorrect to neither await a synchronized() call nor return its Future.
    await synchronized(() async {
      if(!_started)
        return;
      // perform the stop operation`enter code here`
      await Future.delayed(Duration(seconds: 1));
      print("Stopped");
      _started = false;
    });
  }
}

// Prints:
//   Started
//   Stopped
main() async {
  var a = SomeActivity();
  print("Hello");
  a.start();
  a.start();
  a.stop();
  await a.stop();
}
Future<dynamic> lastCallFuture;

Future<T> myAsyncFunction<T>(T value) async {
  if(lastCallFuture != null) {
    await lastCallFuture;
  }
  return lastCallFuture = _myAsyncFunction(value);
}

Future<T> _myAsyncFunction<T>(T value) async => value;
 Stock resultStockQueryByBarcodeAsync;
  bool waitStockQueryByBarcodeAsyncCompleted = false;

  Stock WaitStockQueryByBarcodeAsync(String barcode, int timeOut) {
    CallStockQueryByBarcodeAsync(barcode);
    var startTime = new DateTime.now();
    while (!waitStockQueryByBarcodeAsyncCompleted) {
      Duration difference = DateTime.now().difference(startTime);
      if (difference.inMilliseconds > timeOut) {
        throw TimeoutException("Timeout Exceeded");
      }
      //we must scope time. Because it can be enter endless loop.
    }
    return resultStockQueryByBarcodeAsync;
  }

  void CallStockQueryByBarcodeAsync(String barcode) async {
    waitStockQueryByBarcodeAsyncCompleted = false;
    resultStockQueryByBarcodeAsync = null;
    var stock = await StockQueryByBarcodeAsync(barcode);/*your target async method*/
    waitStockQueryByBarcodeAsyncCompleted = true;
    resultStockQueryByBarcodeAsync = stock;
  }
loadData() async {
  String dataURL = "https://jsonplaceholder.typicode.com/posts";
  http.Response response = await http.get(dataURL);
  setState(() {
    widgets = jsonDecode(response.body);
  });
}
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(SampleApp());
}

class SampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Sample App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SampleAppPage(),
    );
  }
}

class SampleAppPage extends StatefulWidget {
  SampleAppPage({Key key}) : super(key: key);

  @override
  _SampleAppPageState createState() => _SampleAppPageState();
}

class _SampleAppPageState extends State<SampleAppPage> {
  List widgets = [];

  @override
  void initState() {
    super.initState();
    loadData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Sample App"),
      ),
      body: ListView.builder(
          itemCount: widgets.length,
          itemBuilder: (BuildContext context, int position) {
            return getRow(position);
          }));
  }

  Widget getRow(int i) {
    return Padding(
      padding: EdgeInsets.all(10.0),
      child: Text("Row ${widgets[i]["title"]}")
    );
  }

  loadData() async {
    String dataURL = "https://jsonplaceholder.typicode.com/posts";
    http.Response response = await http.get(dataURL);
    setState(() {
      widgets = jsonDecode(response.body);
    });
  }
}