6

与 TWAIN 通信的哪些部分可以放入另一个线程,例如 BackgroundWorker?或者:是否可以拆分处理图像传输的循环?

一些扫描仪驱动程序在返回调用应用程序之前扫描所有图像,这会强制应用程序一次处理所有图像。当突然必须立即处理所有事件(在每个扫描图像后引发)时,这会导致例如 OutOfMemoryException 或我的 WPF 应用程序中的奇怪行为。此外,应用程序挂起,直到传输完成。

我正在使用 TwainDotNet: http ://code.google.com/p/twaindotnet/但我也在寻找一个通用的解决方案来描述消息过滤器以及与 TwainDotNet 无关的 TWAIN 的交互。包含 TWAIN 消息的工作流就足够了。也欢迎其他语言,最好是 C 或 Deplhi 之类的语言。

DataSourceManager 中消息过滤器的当前实现可以描述如下:

  • 从窗口句柄 (hwnd) 获取消息信息
  • 复杂的过滤器,将东西发送到 TWAIN 等。
  • 如果消息关闭(例如,当按下 TWAIN UI 中的取消按钮时)
    • 关闭数据源
    • 禁用过滤器
    • 呼叫扫描完成事件
  • 如果消息传输准备好:
    • 在一个循环中(直到 ADF 为空等,这会阻止消息过滤器)
      • 获取图像
      • 将图像指针转换为 GDI+ 图像
      • 以图像为参数调用 TransferImage 事件
    • 重置转移
    • 关闭数据源等(同消息关闭)
  • 通知窗口,消息已被处理

我已经用几个扫描仪对此进行了测试:

  • 每次传输页面时,富士通 fi-5120C 都会调用 TransferImage 事件。该图像会立即在我的 WPF 应用程序的图像列表中弹出。
  • 佳能 DR-5010C 会阻止我的 WPF 应用程序,直到扫描完所有图像(直到循环结束)。Windows 甚至说,WPF 应用程序没有响应。传输完所有图像后,仅显示少数图像,图像列表中的选择闪烁等。

我不关心显示问题,而是关心窗口阻塞和内存问题。将传输图像的循环放入 BackgroundWorker 导致了几次崩溃,我无法调试。当然,我考虑了 WPF 的线程问题。我也不知道如何拆分传输循环,以便在传输一张图像后,程序返回消息过滤器并且可以将消息标记为已处理。

4

1 回答 1

8

我为 Atalasoft 工作,但我不了解 WPF,甚至不了解 DotTwain!

我可以告诉你,通常 TWAIN 扫描可以在单独的扫描线程上完成,但你必须小心。最简单的方法是在扫描线程上执行所有 TWAIN 操作 - 不要在两个线程之间混合 TWAIN 调用。

扫描线程必须有一个消息泵或者是一个“UI”线程,无论你的环境中需要什么。它不仅仅是一个工作线程。

TWAIN 期望获得一个窗口句柄(老式 Win32 HWND),以用作扫描仪 UI 的父窗口。为此,我建议在扫描线程上创建一个“扫描父级”窗口。您可以选择使其可见或不可见,并在扫描作业结束时将其销毁。

如果您的扫描作业可能非常大(例如 50 页 400 DPI 颜色),您必须确保扫描过程不会填满逻辑内存或 RAM。如果你填满了逻辑内存(一个 32 位 Windows 进程获得大约 2GB 的地址空间来使用)分配将会失败。如果你填满了 RAM,消耗/处理传入图像的代码可能会开始交换,从根本上减慢,然后扫描会提前运行并填满逻辑内存。所以你需要:

  1. 在扫描线程上完全处理和处置每个传入的图像,或
  2. 限制来自扫描线程的图像流,使其不能在处理/处置之前运行太远。

我通常发现我希望能够取消扫描线程,这需要一些耐心,因为 TWAIN 调用无法中断,而且其中一些调用很重。正如您对佳能所注意到的那样。另一方面,如果您在 TWAIN 调用中强制终止线程,则扫描程序可能需要重启电源甚至重新启动系统,并且 TWAIN 本身将阻塞,直到 TWAIN 管理器 DLL 从内存中卸载并重新加载。通常最好非常礼貌地关闭 TWAIN。

于 2013-04-08T14:54:11.640 回答