问题描述
我正在尝试开发一个可让多个用户登录并同时完成民意测验的应用程序.
I am trying to develop an app where multiple users log in and completes a poll concurrently.
在这种情况下,用户提交答案后,便立即运行交易以增加给定答案的计数器
In this, as soon as user submits the answer the transaction is ran to increment the counter for given answer
try {
DocumentSnapshot freshsnap = await tx.get(reff);
try {
await tx.update(reff, <String, dynamic>{
'$i': freshsnap['$i'] + 1,
});
} catch (error) {
print("Error" + error.code);
}
} catch (error) {
if (error is PlatformException &&
error.code == 'Error performing transaction') {
// await tx.set(ref, data);
print("Error" + error.code);
} else
rethrow;
}
}).catchError((onError){
print("Error on: "+onError);
});
多个用户同时提交同一问题的相同答案,即多个用户同时请求更新同一文档中的同一字段,应用崩溃,并产生以下错误:
as soon as the multiple users submit the same answer for same question concurrently i.e The same field in same document is requested to update by multiple users concurrently the app crashes and generates following error:
FATAL EXCEPTION: AsyncTask #1
E/AndroidRuntime(12169): Process: com.rrcg.tumerboared, PID: 12169
E/AndroidRuntime(12169): java.lang.RuntimeException: An error occurred while executing doInBackground()
E/AndroidRuntime(12169): at android.os.AsyncTask$3.done(AsyncTask.java:354)
E/AndroidRuntime(12169): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
E/AndroidRuntime(12169): at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
E/AndroidRuntime(12169): at java.util.concurrent.FutureTask.run(FutureTask.java:271)
E/AndroidRuntime(12169): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
E/AndroidRuntime(12169): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
E/AndroidRuntime(12169): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E/AndroidRuntime(12169): at java.lang.Thread.run(Thread.java:764)
E/AndroidRuntime(12169): Caused by: java.lang.AssertionError: INTERNAL ASSERTION FAILED: A transaction object cannot be used after its update callback has been invoked.
E/AndroidRuntime(12169): at com.google.firebase.firestore.util.Assert.fail(com.google.firebase:firebase-firestore@@21.2.1:46)
E/AndroidRuntime(12169): at com.google.firebase.firestore.util.Assert.hardAssert(com.google.firebase:firebase-firestore@@21.2.1:31)
E/AndroidRuntime(12169): at com.google.firebase.firestore.core.Transaction.ensureCommitNotCalled(com.google.firebase:firebase-firestore@@21.2.1:246)
E/AndroidRuntime(12169): at com.google.firebase.firestore.core.Transaction.lookup(com.google.firebase:firebase-firestore@@21.2.1:81)
E/AndroidRuntime(12169): at com.google.firebase.firestore.Transaction.getAsync(com.google.firebase:firebase-firestore@@21.2.1:191)
E/AndroidRuntime(12169): at com.google.firebase.firestore.Transaction.get(com.google.firebase:firebase-firestore@@21.2.1:228)
E/AndroidRuntime(12169): at io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin$5.doInBackground(CloudFirestorePlugin.java:550)
E/AndroidRuntime(12169): at io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin$5.doInBackground(CloudFirestorePlugin.java:545)
E/AndroidRuntime(12169): at android.os.AsyncTask$2.call(AsyncTask.java:333)
E/AndroidRuntime(12169): at java.util.concurrent.FutureTask.run(FutureTask.java:266)
E/AndroidRuntime(12169): ... 4 more
不知道为什么会这样,因为事务处理应允许多个用户同时更新文档的字段.
Have no idea why is this happening, since transaction should allow multiple users to update a field of a document concurrently.
推荐答案
我通过使事务对象(tx)非异步并将异步逻辑移到事务块之外来解决了这一问题.毕竟,事务的全部目的是原子地执行其指令,而异步指令则有损于此目的.
I solved this by making the transaction object (tx) non-async and moving the async logic outside the transaction block. After all, the whole point of transactions is to execute its instructions atomically and async instructions kind of defeat this purpose.
这篇关于Flutter应用在Cloud Firestore上执行的并发事务时崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!