praeclarum/sqlite-net — pull request #73 by damirarh (2012-07-08 16:12:49+00:00)
Title: Fixed RunInTransactionAsync to prevent deadlocks

Using SQLiteAsyncConnection inside RunInTransactionAsync's delegate caused a deadlock when any task started inside its method calls ended up in a different thread - both threads were trying to obtain a lock on the same connection.

The new method passes SQLiteConnection to the delegate instead, preventing this situation. The delegate doesn't really need to obtain a lock since it runs synchronously with the rest of the transaction.

The delegates are also easier to write now without the need to call Wait() at the end of each asynchronous database call inside it. The complete transaction still runs asynchronously to the calling code as it should.

Before the change the deadlock was occasionally happening to me in my application code but I couldn't consistently reproduce it in a test. To achieve that I'd have to force Task.Factory.StartNew() to start a task on a new thread, but I don't know how to do that. Still, it did happen most of the time if I debuged the test end put a breakpoint just after obtaining a lock in RunInTransactionAsync().