【问题标题】:Is there a way to abort an SQLite call?有没有办法中止 SQLite 调用?
【发布时间】: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 线程的响应。

标签: c++ c windows sqlite


【解决方案1】:

我不明白你为什么希望中断来自同一个线程,我什至不明白这怎么可能:如果当前线程被阻塞,等待一些 IO ,您不能执行任何其他代码。 (是的,这就是“阻塞”的意思)

也许如果你给我们更多关于你为什么想要这个的提示,我们可能会提供进一步的帮助。

通常,我使用sqlite3_interrupt() 取消通话。但这显然涉及到调用是从另一个线程进行的。

【讨论】:

  • 是的:同时做两件事会在某种程度上涉及两个线程。
  • 我已经编辑了这个问题。请阅读更改,我解释我的意思
  • @valdo:我对重叠 IO 非常熟悉,如果它允许你不创建另一个线程,它会在下面使用一个线程:没有魔法,你只是不必关心它。无论如何,如果你的线程因为写东西而被“阻塞”,它就不是idle,也不会浪费资源。作为一般规则,不要事后猜测性能问题。如果您的代码确实存在性能问题,请对其进行分析。但问题往往不是你所期望的。
  • @ereOn:无意冒犯,但我认为您不知道重叠 I/O 的实际工作方式、作业如何传递给驱动程序、IRP 处理、系统 DPC 等。作为 Windows超过 10 年的程序员,无论是内核还是用户端,我都非常了解这些事情。是的,这里有魔法。 Windows 中的设计 WDM 驱动程序知道在硬件级别异步处理 IRP(I/O 请求)。事实与您的想法完全相反:当您执行“阻塞”I/O 时 - 系统实际上发出异步 I/O,然后立即阻塞直到完成
  • @valdo:但是,SQLite 不使用它——对吧?所以这是一个有争议的问题;你需要第二个线程。
【解决方案2】:

默认情况下,SQLite is threadsafe。在我看来,最简单的做法是在后台线程上启动 Sqlite 命令,并让 SQLite 进行必要的锁定以使其工作。

从你的角度来看,sqlite 调用看起来像是一个异步的 I/O,你可以在这个线程上继续正常的处理,例如使用一个循环,包括可中断的睡眠和一些偶尔的后台处理(例如更新活跃度指标)。当 SQLite 语句完成时,后台线程应该设置一个状态变量来指示这一点,唤醒主线程(如果需要),然后终止。

【讨论】:

  • 感谢您的回答。但我的观点是:如果我不想等到 SQLite 完成怎么办?我想尽快打断它。我该怎么做?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-16
  • 1970-01-01
  • 2019-11-17
  • 1970-01-01
  • 2013-12-25
  • 2019-02-15
  • 1970-01-01
相关资源
最近更新 更多