如何异步扫描和传送来自文档进纸器的图像 [英] How can I scan and transfer images from a document feeder asynchronously

查看:218
本文介绍了如何异步扫描和传送来自文档进纸器的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Which parts of the communication with TWAIN can be put into another thread, e.g. a BackgroundWorker? Or: Is it possible to split the loop that handles the image transfer?

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

Some scanner drivers scan all images before returning to the calling application which forces the application to handle all images at once. This results in e.g. OutOfMemoryException or weird behavior in my WPF application when suddenly all events (raised after every scanned image) have to be handled at once. Additionally the application hangs until the transfer was completed.

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

I am using TwainDotNet: http://code.google.com/p/twaindotnet/ but I'm also looking for a generic solution describing the message filter and the interaction with TWAIN independant of TwainDotNet. A workflow containing the TWAIN messages would suffice. Other languages are also welcome, preferrable something like C or Deplhi.

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

The current implementation of the message filter in DataSourceManager can be described as following:

  • 从窗口句柄(hwnd)获取消息信息
  • 使过滤器复杂化,将内容发送到TWAIN等.
  • 如果消息关闭(例如,在TWAIN UI中按取消"按钮时)
    • 关闭数据源
    • 禁用过滤器
    • 呼叫ScanningComplete事件
    • Get message info from window handle (hwnd)
    • Complicate filter, send stuff to TWAIN etc.
    • if message close (e.g. when pressing the cancel button in the TWAIN UI)
      • Close data source
      • Disable filter
      • Call ScanningComplete event
      • 在循环中(直到ADF为空等,这会阻止邮件过滤器)
        • 获取图片
        • In a loop (until the ADF is empty etc., this blocks the message filter)
          • Get image
          • 将图像指针转换为GDI +图像
          • 以图像作为参数调用TransferImage事件

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

          I've tested this with several scanners:

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

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

          I am not concerned about the display problems, but rather about the blocked window and the memory problems. Putting the loop that transfers the images into a BackgroundWorker caused several crashes, that I could not debug. Of cause I considered the threading issues of WPF. I also don't know how to split the transfer loop, so that, after transferring one image, the program returns to the message filter and the message can be marked as handled.

          推荐答案

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

          I work for Atalasoft, but I don't know WPF, or even that much about DotTwain!

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

          I can tell you that generally TWAIN scanning can be done on a separate scanning thread, but you have to take some care. The simplest approach is to do all TWAIN operations on the scanning thread - don't mix TWAIN calls between two threads.

          无论环境如何,扫描线程都必须具有消息泵或为"UI"线程.这不仅仅是一个工作线程.

          The scanning thread has to have a message pump or be a 'UI' thread, whatever that takes in your environment. It is not just a worker thread.

          TWAIN希望获得一个窗口句柄(老式Win32 HWND),以用作扫描仪UI的父窗口.我建议为此在扫描线程上创建扫描父级"窗口.您可以选择是否显示它,并在扫描作业结束时销毁它.

          TWAIN expects to be given a window handle (old-fashioned Win32 HWND) to use as the parent window for the scanner's UI. I recommend creating a 'scanning parent' window for this purpose, on the scanning thread. You can make it visible or not as you choose, and destroy it at the end of the scan job.

          如果扫描作业非常大(例如50页的400 DPI彩色页面),则必须确保扫描过程不会填满逻辑内存或RAM.如果您填满逻辑内存(32位Windows进程获得大约2GB的地址空间可使用),分配将失败.如果您填满了RAM,则消耗/处理传入图像的代码可能会开始交换,从而从根本上放慢速度,然后继续扫描并填满逻辑内存.因此,您需要:

          If your scan jobs can be very big (e.g. 50 pages of 400 DPI color) you have to make sure the scanning process does not fill up either logical memory or RAM. If you fill up logical memory (a 32-bit Windows process gets about 2GB of address space to work with) allocations will fail. If you fill up RAM, the code that is consuming/disposing of the incoming images may start to swap, slowing down radically, then scanning runs ahead and fills up logical memory. So you need to either:

          1. 在扫描过程中完全处理并处理每个传入的图像 线程,或
          2. 限制来自扫描线程的图像流,因此 不能在处理/处置之前跑得太远.
          1. Completely process and dispose of each incoming image on the scan thread, or
          2. Throttle the flow of images from the scan thread so it cannot run too far ahead of their processing/disposition.

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

          I usually find I want to be able to cancel the scan thread, which requires some patience since TWAIN calls cannot be interrupted, and some of them are heavy. As you've noticed with your Canon. On the other hand if you force-kill a thread inside a TWAIN call, the scanner may require a power-cycle or even a system restart, and TWAIN itself will block until the TWAIN manager DLL is unloaded from memory and reloaded. Usually best to shut down TWAIN very politely.

          这篇关于如何异步扫描和传送来自文档进纸器的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆