【发布时间】:2010-10-12 17:57:16
【问题描述】:
我在 Windows 应用程序中使用 SQLite3。我有源代码(所谓的 SQLite 合并)。
有时我必须执行繁重的查询。也就是说,我在准备好的语句上调用sqlite3_step,它需要很长时间才能完成(由于 I/O 负载很重)。
我想知道是否有可能中止这样的呼叫。如果能够在调用过程中在同一个线程中进行一些后台处理,我也会很高兴(因为大部分时间都花在等待 I/O 完成上) .
我想过自己修改 SQLite 代码。在最简单的情况下,我可以在每次调用 ReadFile/WriteFile 之前检查一些条件(例如中止事件句柄),并适当地返回错误代码。并且为了允许后台处理文件应该以重叠模式打开(这会启用异步ReadFile/WriteFile)。
WriteFile 的中断是否有可能在某些情况下使数据库处于不一致状态,即使启用了日志?我猜不是,因为日志文件的整个想法是为任何类型的错误做好准备。但我想听听更多关于这方面的意见。
另外,有人尝试过类似的方法吗?
提前致谢。
编辑:
感谢ereOn。我不知道sqlite3_interrupt 的存在。这可能回答了我的问题。
现在,对于所有想知道如何(以及为什么)希望在同一线程中的 I/O 期间进行一些后台处理的人。
遗憾的是,没有多少人熟悉所谓的“重叠 I/O”。
http://en.wikipedia.org/wiki/Overlapped_I/O
使用它异步发出 I/O 操作,调用线程未阻塞。然后使用以下完成机制之一接收 I/O 完成状态:等待事件、排队进入 APC 的新例程或完成端口。
使用这种技术不需要创建额外的线程。实际上,创建线程的唯一真正合法性是当您的瓶颈是计算时间(即 CPU 负载),并且机器有多个 CPU(或内核)时。
创建一个线程只是为了让它在大多数时候被操作系统阻塞——这没有意义。这会导致操作系统资源的不合理浪费,使程序复杂化(需要同步等)。
不幸的是,并非所有库/API 都允许异步操作模式,因此创建额外的线程必然是邪恶的。
EDIT2:
我已经找到了解决方案,谢谢ereOn。
对于那些仍然坚持认为在“等待”I/O 使用重叠 I/O 完成时不值得“在后台”执行操作的人。我不同意,我认为没有必要争论这个。至少这与主题无关。
我是一名 Windows 程序员(您可能已经注意到了),并且在各种多任务处理方面拥有非常丰富的经验。另外,我也是一名司机作家,因此我也知道“幕后”的运作方式。
我知道创建多个线程来“并行”执行几件事是一种“常见做法”。但这并不意味着这是一个好的做法。请允许我不要遵循“惯例”。
【问题讨论】:
-
哇。在不完全理解的情况下编辑 SQLite 源代码?祝你好运。
-
幸运的是,有一个地方调用了“WriteFile”(它被一些 SQLite 函数包装)。我的意思是 - 只修改它
-
为什么一定要在同一个线程中?
-
同意 Eamon Nerbonne 的观点。请告诉我们您的问题是什么,而不是寻求一种方法来实现可感知的解决方案。
-
@valdo:您离“创建线程的唯一真正合法性”还差得很远。创建后台工作线程是一种常见且有用的技术,可在执行大量计算时保持 UI 响应。先验地,这不需要多个核心才能有效。它当然不会加速应用程序(除非 CPU 支持硬件线程并且计算受内存限制),但这不是后台工作线程的目的。目的仅仅是为了保持 UI 线程的响应。