mirror of
https://github.com/soukoku/ntwain.git
synced 2025-07-16 21:23:57 +08:00
Timing hack for file transfer.
This commit is contained in:
parent
69d90aa945
commit
6b35b1735d
@ -36,7 +36,9 @@ namespace WinConsole32
|
|||||||
Console.WriteLine($"Default data source = {defaultSrc}");
|
Console.WriteLine($"Default data source = {defaultSrc}");
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
|
|
||||||
twain.ShowUserSelect();
|
sts = twain.ShowUserSelect();
|
||||||
|
if (sts.IsSuccess)
|
||||||
|
{
|
||||||
Console.WriteLine($"Selected data source = {twain.DefaultSource}");
|
Console.WriteLine($"Selected data source = {twain.DefaultSource}");
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
|
|
||||||
@ -58,6 +60,7 @@ namespace WinConsole32
|
|||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
twain.TryStepdown(STATE.S1);
|
twain.TryStepdown(STATE.S1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Failed to attach: " + sts);
|
Console.WriteLine("Failed to attach: " + sts);
|
||||||
@ -115,7 +118,7 @@ namespace WinConsole32
|
|||||||
|
|
||||||
TW_SETUPFILEXFER setup = new()
|
TW_SETUPFILEXFER setup = new()
|
||||||
{
|
{
|
||||||
FileName = targetName,
|
FileName = Path.Combine("Images", targetName),
|
||||||
Format = format,
|
Format = format,
|
||||||
};
|
};
|
||||||
e.SetupFileTransfer(ref setup);
|
e.SetupFileTransfer(ref setup);
|
||||||
@ -171,9 +174,11 @@ namespace WinConsole32
|
|||||||
{
|
{
|
||||||
watch.Stop();
|
watch.Stop();
|
||||||
var elapsed = watch.Elapsed;
|
var elapsed = watch.Elapsed;
|
||||||
Console.WriteLine($"Session source disabled, took {elapsed}.");
|
Console.WriteLine($"Session source disabled, took {elapsed}, will retest in 3 sec...");
|
||||||
|
|
||||||
//TestThisSource(twain, e);
|
Thread.Sleep(3000);
|
||||||
|
if (twain.State > STATE.S3)
|
||||||
|
TestThisSource(twain, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TestThisSource(TwainAppSession twain, TW_IDENTITY_LEGACY source)
|
private static void TestThisSource(TwainAppSession twain, TW_IDENTITY_LEGACY source)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!--change these in each release-->
|
<!--change these in each release-->
|
||||||
<VersionPrefix>4.0.0.0</VersionPrefix>
|
<VersionPrefix>4.0.0.0</VersionPrefix>
|
||||||
<VersionSuffix>alpha.7</VersionSuffix>
|
<VersionSuffix>alpha.8</VersionSuffix>
|
||||||
|
|
||||||
<!--keep it the same until major # changes-->
|
<!--keep it the same until major # changes-->
|
||||||
<AssemblyVersion>4.0.0.0</AssemblyVersion>
|
<AssemblyVersion>4.0.0.0</AssemblyVersion>
|
||||||
|
@ -9,8 +9,7 @@ using System.Windows.Forms;
|
|||||||
namespace NTwain
|
namespace NTwain
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For use under Windows to host a message pump in non-winform/wpf apps.
|
/// For use under Windows to host a message pump.
|
||||||
/// This is highly experimental.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class MessagePumpThread
|
class MessagePumpThread
|
||||||
{
|
{
|
||||||
|
@ -98,6 +98,13 @@ namespace NTwain
|
|||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
case MSG.XFERREADY:
|
case MSG.XFERREADY:
|
||||||
|
if (_transferInCallbackThread)
|
||||||
|
{
|
||||||
|
EnterTransferRoutine();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// use bg thread to process transfer.
|
||||||
// some sources spam this even during transfer so we gate it
|
// some sources spam this even during transfer so we gate it
|
||||||
if (!_inTransfer)
|
if (!_inTransfer)
|
||||||
{
|
{
|
||||||
@ -105,6 +112,7 @@ namespace NTwain
|
|||||||
_xferReady.Set();
|
_xferReady.Set();
|
||||||
//_bgPendingMsgs.Add(msg);
|
//_bgPendingMsgs.Add(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MSG.CLOSEDSOK:
|
case MSG.CLOSEDSOK:
|
||||||
case MSG.CLOSEDSREQ:
|
case MSG.CLOSEDSREQ:
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
using NTwain.Native;
|
using NTwain.Native;
|
||||||
using NTwain.Triplets;
|
using NTwain.Triplets;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace NTwain
|
namespace NTwain
|
||||||
{
|
{
|
||||||
@ -161,7 +163,7 @@ namespace NTwain
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HandleXferCode(ref sts, ref pending);
|
HandleXferCode(ref sts, ref pending, isEnd: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -176,7 +178,7 @@ namespace NTwain
|
|||||||
} while (sts.RC == TWRC.SUCCESS && pending.Count != 0);
|
} while (sts.RC == TWRC.SUCCESS && pending.Count != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleXferCode(ref sts, ref pending);
|
HandleXferCode(ref sts, ref pending, isEnd: true);
|
||||||
|
|
||||||
if (State >= STATE.S5)
|
if (State >= STATE.S5)
|
||||||
{
|
{
|
||||||
@ -185,13 +187,17 @@ namespace NTwain
|
|||||||
_inTransfer = false;
|
_inTransfer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleXferCode(ref STS sts, ref TW_PENDINGXFERS pending)
|
private void HandleXferCode(ref STS sts, ref TW_PENDINGXFERS pending, bool isEnd)
|
||||||
{
|
{
|
||||||
switch (sts.RC)
|
switch (sts.RC)
|
||||||
{
|
{
|
||||||
case TWRC.SUCCESS:
|
case TWRC.SUCCESS:
|
||||||
case TWRC.XFERDONE:
|
case TWRC.XFERDONE:
|
||||||
// ok to keep going
|
// ok to keep going
|
||||||
|
if (isEnd)
|
||||||
|
{
|
||||||
|
//DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TWRC.CANCEL:
|
case TWRC.CANCEL:
|
||||||
// might eventually have option to cancel this or all like transfer ready
|
// might eventually have option to cancel this or all like transfer ready
|
||||||
@ -210,6 +216,18 @@ namespace NTwain
|
|||||||
// TODO: raise error event
|
// TODO: raise error event
|
||||||
switch (sts.STATUS.ConditionCode)
|
switch (sts.STATUS.ConditionCode)
|
||||||
{
|
{
|
||||||
|
case TWCC.SEQERROR:
|
||||||
|
if (isEnd)
|
||||||
|
{
|
||||||
|
// special break down to state 5
|
||||||
|
pending = TW_PENDINGXFERS.DONTCARE();
|
||||||
|
sts = WrapInSTS(DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending));
|
||||||
|
State = STATE.S6;
|
||||||
|
pending = TW_PENDINGXFERS.DONTCARE();
|
||||||
|
sts = WrapInSTS(DGControl.PendingXfers.Reset(ref _appIdentity, ref _currentDS, ref pending));
|
||||||
|
State = STATE.S5;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case TWCC.DAMAGEDCORNER:
|
case TWCC.DAMAGEDCORNER:
|
||||||
case TWCC.DOCTOODARK:
|
case TWCC.DOCTOODARK:
|
||||||
case TWCC.DOCTOOLIGHT:
|
case TWCC.DOCTOOLIGHT:
|
||||||
@ -245,6 +263,7 @@ namespace NTwain
|
|||||||
|
|
||||||
// and just start it
|
// and just start it
|
||||||
var sts = WrapInSTS(DGAudio.AudioFileXfer.Get(ref _appIdentity, ref _currentDS));
|
var sts = WrapInSTS(DGAudio.AudioFileXfer.Get(ref _appIdentity, ref _currentDS));
|
||||||
|
|
||||||
if (sts.RC == TWRC.XFERDONE)
|
if (sts.RC == TWRC.XFERDONE)
|
||||||
{
|
{
|
||||||
State = STATE.S7;
|
State = STATE.S7;
|
||||||
@ -475,7 +494,11 @@ namespace NTwain
|
|||||||
// get what will be transferred
|
// get what will be transferred
|
||||||
DGControl.SetupFileXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPFILEXFER fileSetup);
|
DGControl.SetupFileXfer.Get(ref _appIdentity, ref _currentDS, out TW_SETUPFILEXFER fileSetup);
|
||||||
// and just start it
|
// and just start it
|
||||||
|
|
||||||
|
int tries = 0;
|
||||||
|
RETRY:
|
||||||
var sts = WrapInSTS(DGImage.ImageFileXfer.Get(ref _appIdentity, ref _currentDS));
|
var sts = WrapInSTS(DGImage.ImageFileXfer.Get(ref _appIdentity, ref _currentDS));
|
||||||
|
|
||||||
if (sts.RC == TWRC.XFERDONE)
|
if (sts.RC == TWRC.XFERDONE)
|
||||||
{
|
{
|
||||||
State = STATE.S7;
|
State = STATE.S7;
|
||||||
@ -494,6 +517,23 @@ namespace NTwain
|
|||||||
State = pending.Count == 0 ? STATE.S5 : STATE.S6;
|
State = pending.Count == 0 ? STATE.S5 : STATE.S6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// sometimes it errors only due to timing so wait a bit and try again
|
||||||
|
if (sts.RC == TWRC.FAILURE && (sts.ConditionCode == TWCC.None || sts.ConditionCode == TWCC.SEQERROR))
|
||||||
|
{
|
||||||
|
if (tries++ < 3)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"Using fileXfer timing workaround try {tries}.");
|
||||||
|
Thread.Sleep(500);
|
||||||
|
goto RETRY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debugger.Break();
|
||||||
|
}
|
||||||
|
}
|
||||||
return sts;
|
return sts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ namespace NTwain
|
|||||||
bool _inTransfer;
|
bool _inTransfer;
|
||||||
readonly AutoResetEvent _xferReady = new(false);
|
readonly AutoResetEvent _xferReady = new(false);
|
||||||
private bool disposedValue;
|
private bool disposedValue;
|
||||||
|
bool _transferInCallbackThread = true;
|
||||||
|
|
||||||
void StartTransferThread()
|
void StartTransferThread()
|
||||||
{
|
{
|
||||||
@ -114,7 +115,7 @@ namespace NTwain
|
|||||||
#if WINDOWS || NETFRAMEWORK
|
#if WINDOWS || NETFRAMEWORK
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads and opens the TWAIN data source manager in a self-hosted message queue thread.
|
/// Loads and opens the TWAIN data source manager in a self-hosted message queue thread.
|
||||||
/// Highly experimental and only use if necessary. Must close with <see cref="CloseDSMAsync"/>
|
/// Must close with <see cref="CloseDSMAsync"/>
|
||||||
/// if used.
|
/// if used.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@ -122,6 +123,7 @@ namespace NTwain
|
|||||||
{
|
{
|
||||||
if (_selfPump == null)
|
if (_selfPump == null)
|
||||||
{
|
{
|
||||||
|
_transferInCallbackThread = true;
|
||||||
var pump = new MessagePumpThread();
|
var pump = new MessagePumpThread();
|
||||||
var sts = await pump.AttachAsync(this);
|
var sts = await pump.AttachAsync(this);
|
||||||
if (sts.IsSuccess)
|
if (sts.IsSuccess)
|
||||||
@ -162,6 +164,7 @@ namespace NTwain
|
|||||||
var rc = DGControl.Parent.OpenDSM(ref _appIdentity, hwnd);
|
var rc = DGControl.Parent.OpenDSM(ref _appIdentity, hwnd);
|
||||||
if (rc == TWRC.SUCCESS)
|
if (rc == TWRC.SUCCESS)
|
||||||
{
|
{
|
||||||
|
_transferInCallbackThread = true;
|
||||||
_hwnd = hwnd;
|
_hwnd = hwnd;
|
||||||
_pumpThreadMarshaller = uiThreadMarshaller;
|
_pumpThreadMarshaller = uiThreadMarshaller;
|
||||||
State = STATE.S3;
|
State = STATE.S3;
|
||||||
@ -296,7 +299,14 @@ namespace NTwain
|
|||||||
{
|
{
|
||||||
// todo: finish
|
// todo: finish
|
||||||
case STATE.S7:
|
case STATE.S7:
|
||||||
|
var pending = TW_PENDINGXFERS.DONTCARE();
|
||||||
|
DGControl.PendingXfers.EndXfer(ref _appIdentity, ref _currentDS, ref pending);
|
||||||
|
_state = STATE.S6;
|
||||||
|
break;
|
||||||
case STATE.S6:
|
case STATE.S6:
|
||||||
|
pending = TW_PENDINGXFERS.DONTCARE();
|
||||||
|
DGControl.PendingXfers.Reset(ref _appIdentity, ref _currentDS, ref pending);
|
||||||
|
_state = STATE.S5;
|
||||||
break;
|
break;
|
||||||
case STATE.S5:
|
case STATE.S5:
|
||||||
DisableSource();
|
DisableSource();
|
||||||
|
Loading…
Reference in New Issue
Block a user