0

I have a C# program that uses TwainDotNet to scan and receive images from a fujitsu scanner. I have working code, but I want to perform scanning and image transfer asynchronously because the GUI hangs until the scan process is complete.

I attempted to follow the guidelines from this post's accepted solution using this code:

public void StartScanning()
{
    // Run the scanner from a separate thread
    Task.Run(() => ScanThread());
}

private void ScanThread()
{
    // Instantiate the Twain object and hookup event handlers
    Twain twain = new Twain(new WinFormsWindowMessageHook(new Form()));
    twain.TransferImage += Twain_TransferImage;
    twain.ScanningComplete += Twain_ScanningComplete;

    // Start the scanning process by passing along pre-defined scan settings
    twain.StartScanning(GetScanSettings());
}

The code inside ScanThread() is technically correct, because it works outside of the call to Task.Run() (meaning it runs fine on the GUI thread). However, ScanThread() does not work if called from a new thread. The scanner hardware never begins to scan images, let alone transfer them.

Does anyone know of a concrete way to scan and transfer images asynchronously using TWAIN?

Richard
  • 1
  • 3

1 Answers1

0

I suspect the "simple" answer is "you can't".

The more involved answer is that "twain" (or possibly "GetScanSettings" - what does this do?) is likely to require operations to be performed on the UI thread.

See: TwainDotNet Scanning using TWAIN with BackgroundWorker

However, it might be possible, using the code you've got, except that the form you create likely goes out of scope almost immediately if the references are weak (such as event delegate).

Try adding a Thread Safe list or dictionary, adding your form to it when you create it, and removing it in Twain_ScanningComplete.

Hmm. Actually, try

private ConcurrentDictionary<Twain,Form> m_References = new ConcurrentDictionary<Twain,Form>();


private void ScanThread()
{
    // Instantiate the Twain object and hookup event handlers
    Form frm = new Form();
    Twain twain = new Twain(new WinFormsWindowMessageHook(frm));
    m_References.Add(twain, frm);

    twain.TransferImage += Twain_TransferImage;
    twain.ScanningComplete += Twain_ScanningComplete;

    // Start the scanning process by passing along pre-defined scan settings
    twain.StartScanning(GetScanSettings());
}


private void Twain_ScanningComplete(object sender, ScanningCompleteEventArgs args)
{
    Form frm;
    m_References.TryRemove((Twain) sender, out frm);
    if(null != frm)
    {
       frm.Close();
    }
}
Roger Willcocks
  • 1,649
  • 13
  • 27
  • Thank you for the detailed suggestion. I attempted this but the result was the same -- the scanner hardware never starts. I've read old posts saying asynchronous image transfer _is_ and _isn't_ possible and thought i'd give it a try in 2017. – Richard Jul 06 '17 at 22:14
  • And just to clarify: `GetScanSettings()` is a convenience method for returning a `ScanSettings` object specific to TwainDotNet. The object is a container for fields that may or may not be used by a particular scanner. – Richard Jul 06 '17 at 22:20
  • Can you serialize the result of "GetScanSettings" somewhere and compare them, just to see if there's a difference in the result? – Roger Willcocks Jul 08 '17 at 11:45