如何将dart sqlite代码从同步样式更改为异步样式?

如何将dart sqlite代码从同步样式更改为异步样式?,sqlite,asynchronous,dart,synchronous,Sqlite,Asynchronous,Dart,Synchronous,我正在尝试将Dart用于sqlite,用于这个项目 但我发现了一个问题:它提供的API是同步风格的。代码如下所示: // Iterating over a result set var count = c.execute("SELECT * FROM posts LIMIT 10", callback: (row) { print("${row.title}: ${row.body}"); }); print("Showing ${count} posts."); 有了这样的代码,我无

我正在尝试将Dart用于sqlite,用于这个项目

但我发现了一个问题:它提供的API是同步风格的。代码如下所示:

// Iterating over a result set
var count = c.execute("SELECT * FROM posts LIMIT 10", callback: (row) {
    print("${row.title}: ${row.body}");
});
print("Showing ${count} posts.");
有了这样的代码,我无法使用Dart未来的支持,代码将在sql操作时阻塞

我想知道如何将代码更改为异步样式?您可以在这里看到它定义了一些
本机
函数:

本地函数映射到一些C++函数:

是否可以更改为异步?如果可能,我该怎么办

如果不可能,我必须重写它,我是否必须重写所有:

  • 省道锉刀
  • C++包装文件
  • 实际的sqlite驱动程序

  • 更新:

    感谢@GregLowe的评论,Dart的
    Completer
    可以将回调样式转换为未来样式,这可以让我使用Dart的
    doSomething()。然后(…)
    而不是传递回调函数

    但是在阅读了dart sqlite的源代码之后,我意识到,在dart sqlite的实现中,
    回调
    不是基于事件的:

    int execute([params = const [], bool callback(Row)]) {
      _checkOpen();
      _reset(_statement);
      if (params.length > 0) _bind(_statement, params);
      var result;
      int count = 0;
      var info = null;
      while ((result = _step(_statement)) is! int) {
        count++;
        if (info == null) info = new _ResultInfo(_column_info(_statement));
        if (callback != null && callback(new Row._internal(count - 1, info, result)) == true) {
          result = count;
          break;
        }
      }
      // If update affected no rows, count == result == 0
      return (count == 0) ? result : count;
    }
    

    即使我使用了
    Completer
    ,它也不会提高性能。我想我可能必须重写C++代码,使它成为事件的基础。

    < P>你应该能够写一个包装器而不接触C++。看看如何在dart:async中使用Completer类。基本上,您需要创建一个Completer,立即返回Completer.future,然后从现有回调调用Completer.complete(行)


    回复:更新。你看到了吗,特别是关于异步扩展的部分?也就是说,如果C++ API是同步的,则可以在单独的线程中运行它,并使用消息传递与它通信。这可能是一种方法

    您遇到的最大问题是SQLite是一个嵌入式数据库;为了处理您的查询并提供结果,它必须在您的过程中进行计算(和I/O)。更重要的是,为了使其事务处理系统能够工作,它需要将其连接置于中,或者让您以序列化模式运行(性能受到影响)

    因为这些都是相当严格的限制,所以除非使用多个线程,否则将事情切换到异步操作模式的计划不太可能顺利进行。因为使用多个连接会使事情复杂化(因为你不能在它们之间共享一些东西,比如<代码>临时表< /代码> s),让我们考虑一个串行化的连接;所有活动都将在DB级别序列化,但对于不经常使用DB的应用程序来说,这是可以的。在C++级别,您将从另一个线程调用“<代码>执行< /代码>,然后将消息发送回调用方线程,以指示每行和完成。 但是当你这样做的时候,你会受到真正的打击;特别是,您承诺一次只执行一个查询,因为当您开始同时使用两个连接时,该技术在语义效果方面遇到了重大问题,而DB强制您使用一个连接进行序列化

    通过在Dart级别管理工作线程和线程间通信,将同步异步耦合放在Dart级别可能更简单。这将使您避免显著改变C++代码。我对达特不太了解,所以不能在那里提供很多建议


    对于我自己,我只会坚持同步连接处理,这样我就可以让我的应用程序更有效地使用多线程模式。我将在语义上受到影响,并为每个线程提供其自己的连接(可能是延迟分配的),这样总体速度会更好,但我确实来自一个编程社区,它认为线程是相对重要的资源,所以您可以这样做。(重线程可以减少它们所需的锁的数量,而轻线程则没有意义;这是关于开销管理的。)

    这段代码已经过时,因为它是两年前编写的。所以,你的问题还是不现实。除了如果你不想自己重写它(dart sqlite),我修改了代码,使它可以正确运行,但我不喜欢代码样式。如果我想要异步风格,我必须重写代码?我是否需要重写驱动程序部分(C/C++)来支持异步?你应该能够写一个包装器而不接触C++。看看如何在dart:async中使用Completer类。基本上,您需要创建一个Completer,立即返回Completer.future,然后从现有回调调用Completer.complete(行)。Re:update。您是否看过下面链接的文章,特别是关于异步扩展的部分?也就是说,如果C++ API是同步的,则可以在单独的线程中运行它,并使用消息传递与它通信。这可能是一种方法@格雷格,非常感谢!这正是我想要的,它回答了我所有的问题。请你把它作为回答,我会接受的
    int execute([params = const [], bool callback(Row)]) {
      _checkOpen();
      _reset(_statement);
      if (params.length > 0) _bind(_statement, params);
      var result;
      int count = 0;
      var info = null;
      while ((result = _step(_statement)) is! int) {
        count++;
        if (info == null) info = new _ResultInfo(_column_info(_statement));
        if (callback != null && callback(new Row._internal(count - 1, info, result)) == true) {
          result = count;
          break;
        }
      }
      // If update affected no rows, count == result == 0
      return (count == 0) ? result : count;
    }