gpt4 book ai didi

The await keyword breaks the database function internally in dart(AWAIT关键字在DART内部中断数据库功能)

转载 作者:bug小助手 更新时间:2023-10-26 20:42:25 29 4
gpt4 key购买 nike



I am writing a flutter app and I am trying to insert some data to a local database and give back the primary key the database creates, but somehow the await keyword breaks the function that handles the database interaction. (Following code is a simplified version of my actual code, but has all the essentials and the same issue)

我正在编写一个Ffltter应用程序,我试图将一些数据插入到本地数据库中,并返回数据库创建的主键,但不知何故,AWait关键字破坏了处理数据库交互的功能。(以下代码是我实际代码的简化版本,但包含所有要点和相同的问题)


1.Future<int> insertObjekt(Objekt o) async {
2. final db = await _database;
3. return db.insert('objekt', {'name': o.name});
4.}

If I put breakpoints in lines 2 and 3, line 2 stops as expected, but upon resuming the program never stops for line 3 (i let it run for almost 15 minutes to make sure and nothing happened).

如果我在第2行和第3行设置断点,第2行就会像预期的那样停止,但在继续运行第3行时,程序永远不会停止(我让它运行近15分钟,以确保没有发生任何事情)。


1. class TestState extends ChangeNotifier {
2. var db = tempDB;
3. Objekt? currentObjekt;
4.
5. TestState(){
6. initialize('doesn\'t work');
7. /*Objekt o = Objekt.loaded(1, 'in constructor');
8. db.insertObjekt(o);
9. debugPrint('${o.id}');
10. currentObjekt = o;// */
11. //currentObjekt = Objekt('functions as intended', db);
12. while(currentObjekt == null){
13. sleep(const Duration(milliseconds: 10));
14. }
15. debugPrint('concluded');
16. notifyListeners();
17. }
18.
19. Future<void> initialize(String name) async {
20. Objekt o = Objekt.loaded(1, name);
21. o.id = await db.insertObjekt(o);
22. debugPrint('${o.id}');
23. currentObjekt = o;
24. }
25.}

If I remove the o.id = await in line 21 it works. The problem is, that I need the return value at this spot. Line 7-10 work with inserting and ignoring the return value, but as soon as I try to query (another function same structure as insertObject just with db.query and a cast the the desired class) I need the return value again. Same problem with going through the object itself (although for some reason when going through the object the return value works just fine and I can set the attribute inside the class).

如果我删除第21行中的o.id=aWait,它就可以工作了。问题是,我需要这里的返回值。第7-10行用于插入和忽略返回值,但我一尝试查询(另一个函数,其结构与INSERTObject相同,只是使用了DB.Query,并对所需的类进行强制转换),我就再次需要返回值。检查对象本身也有同样的问题(尽管由于某些原因,在检查对象时,返回值工作得很好,我可以在类中设置属性)。


When running the app it just stays in a endless loading screen, despite the while loop concluding and the line 15 printing to the console as it should. I thought this could be because await 'creating' a new thread, but if a new thread means the return value gets lost then I don't see any point in using async-await. Why does the function insertObjekt just stop after one line and how can make sure I get the desired return value so the database can be read?

当运行应用程序时,它只是停留在一个无休止的加载屏幕上,尽管while循环结束,第15行打印到控制台。我认为这可能是因为await“创建”了一个新线程,但如果一个新线程意味着返回值丢失,那么我不认为使用await有任何意义。为什么函数insertObjekt在一行之后就停止了,如何确保我得到了想要的返回值,以便数据库可以被读取?


Edit to add: The requested implementation of _database

要添加的编辑:_DATABASE的请求实现


1. Future<bool> openDB() async {
2. _database = openDatabase(
3. join(await getDatabasesPath(), 'tappDB.db'),
4. onCreate: (db, version) async {
5. db.execute('''
6. CREATE TABLE objekt(
7. id INTEGER PRIMARY KEY,
8. name TEXT
9. )''');
10. debugPrint("DB built");
11. },
12. version: 4,
13. );
14. debugPrint("DB opened");
15. return true;
16.}

更多回答

Show us your _database implementation

向我们展示您的数据库实现(_D)

"despite the while loop concluding and the line 15 printing to the console as it should". That is not plausible with this code. while (currentObjekt == null) { sleep(...); } will never allow asynchronous operations in that isolate to make any progress. See stackoverflow.com/a/56707357. It appears that loop is trying to make an asynchronous operations synchronous; there is no supported way to do that in Dart. Do not perform asynchronous work in constructors. If you need to do asynchronous initialization, use a static method.

“尽管While循环结束,并且第15行打印到控制台。”这在这段代码中是不可信的。而(currentObjekt==NULL){睡眠(...);}永远不会允许该隔离中的异步操作取得任何进展。见Stackoverflow.com/a/56707357。循环似乎正在尝试使异步操作同步;DART中不支持这样做。不要在构造函数中执行异步工作。如果需要进行异步初始化,请使用静态方法。

And no, await does not create any new thread. Dart isolates are single-threaded. await simply yields; it's syntactic sugar for returning a Future and registering completion callbacks for you.

不,等待不会创建任何新的线程。DART分离株是单线的。等待只会产生结果;它是为您返回Future和注册完成回调的语法糖。

@OzanTaskiran i added the implementation in the post

@OzanTaskiran我在帖子中添加了实现

@jamesdlin then i don't understand even less than i think i did. The line print('concluded'); fires and prints to the console. The loop with sleep was intended to check every 10ms if currentObjekt has been set, because my initial thought was that the database actions took longer than it takes the code to get to the point where currentObjekt is needed/used. Using a static method would help with readability but i dont think it really tackles my problem

@Jamesdlin,那么我甚至不会比我认为的更不理解。命令行print(‘conduced’);触发并打印到控制台。带有睡眠的循环旨在每隔10毫秒检查一次是否设置了CurentObjekt,因为我最初的想法是,数据库操作花费的时间比代码到达需要/使用CurentObjekt的位置所用的时间要长。使用静态方法有助于提高可读性,但我认为它并不能真正解决我的问题

优秀答案推荐


When running the app it just stays in a endless loading screen, despite the while loop concluding and the line 15 printing to the console as it should.


12.    while(currentObjekt == null){
13. sleep(const Duration(milliseconds: 10));
14. }
15. debugPrint('concluded');


That is not plausible with this code. sleep blocks, so your loop will never allow asynchronous operations in that isolate to make any progress. Even if the asynchronous operations are running in a different isolate, the looping isolate would never have any opportunity to set currentObjekt. (Also see stackoverflow.com/a/56707357).

这是不合理的与此代码。休眠块,因此您循环将永远不允许隔离中的异步操作取得任何进展。即使异步操作在不同的隔离中运行,循环隔离也永远没有机会设置currentObjekt。(Also参见stackoverflow.com/a/56707357)。



I thought this could be because await 'creating' a new thread...



No, await does not create any new thread. Dart isolates are single-threaded. await simply yields; it's syntactic sugar for returning a Future and registering completion callbacks for you.

不,等待不会创建任何新线程。DART分离株是单线的。等待只会产生结果;它是为您返回Future和注册完成回调的语法糖。


It appears that loop is trying to make an asynchronous operations synchronous; there is no supported way to do that in Dart. Do not perform asynchronous work in constructors. If you need to do asynchronous initialization, replace the constructor with a static factory method:

循环似乎正在尝试使异步操作同步;DART中不支持这样做。不要在构造函数中执行异步工作。如果需要进行异步初始化,请将构造函数替换为静态工厂方法:


class TestState extends ChangeNotifier {
var db = tempDB;
Objekt? currentObjekt;

TestState._();

static Future<TestState> createTestState() async {
var testState = TestState._();
await testState.initialize('');
debugPrint('concluded');
testState.notifyListeners();
return testState;
}

Future<void> initialize(String name) async {
Objekt o = Objekt.loaded(1, name);
o.id = await db.insertObjekt(o);
debugPrint('${o.id}');
currentObjekt = o;
}
}

Note that the initialize method is now probably redundant and could be merged into createTestState. Also note that asynchronous operations are inherently contagious, so any functions that needs to wait for a TestState object to be constructed also will need to be asynchronous, and anything that calls those functions will need to be asynchronous, and so on.

请注意,initialize方法现在可能是多余的,可以合并到CNORTTestState中。还要注意,异步操作本身就具有传染性,因此任何需要等待TestState对象被构造的函数也需要是异步的,并且任何调用这些函数的函数都需要是异步的,等等。


更多回答

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com