Properly catch and throw exceptions on message loop .invoke() calls (#79)

This commit is contained in:
Eugene Wang 2017-04-24 23:19:13 -04:00
parent 143e36e996
commit 3180e6bcf4
3 changed files with 44 additions and 3 deletions

View File

@ -22,7 +22,14 @@ namespace Sample
// just an amusing example to do twain in console without UI // just an amusing example to do twain in console without UI
ThreadPool.QueueUserWorkItem(o => ThreadPool.QueueUserWorkItem(o =>
{ {
DoTwainWork(); try
{
DoTwainWork();
}
catch (Exception ex)
{
Console.WriteLine("ERROR: " + ex.ToString());
}
}); });
Console.WriteLine("Test started, press Enter to exit."); Console.WriteLine("Test started, press Enter to exit.");
Console.ReadLine(); Console.ReadLine();

View File

@ -71,6 +71,8 @@ namespace NTwain.Internals
{ {
if (_dispatcher == null) { throw new InvalidOperationException(Resources.MsgLoopUnavailble); } if (_dispatcher == null) { throw new InvalidOperationException(Resources.MsgLoopUnavailble); }
Exception error = null;
if (_dispatcher.CheckAccess()) if (_dispatcher.CheckAccess())
{ {
action(); action();
@ -85,6 +87,7 @@ namespace NTwain.Internals
{ {
action(); action();
} }
catch (Exception ex) { error = ex; }
finally finally
{ {
man.Set(); man.Set();
@ -95,8 +98,17 @@ namespace NTwain.Internals
} }
else else
{ {
_dispatcher.Invoke(DispatcherPriority.Normal, action); _dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
try
{
action();
}
catch (Exception ex) { error = ex; }
}));
} }
if (error != null) { Rethrow(error); }
} }
} }
} }

View File

@ -1,5 +1,6 @@
using NTwain.Internals; using NTwain.Internals;
using System; using System;
using System.Reflection;
using System.Threading; using System.Threading;
using System.Windows.Interop; using System.Windows.Interop;
@ -47,13 +48,34 @@ namespace NTwain
} }
else else
{ {
Exception error = null;
SyncContext.Send(o => SyncContext.Send(o =>
{ {
action(); try
{
action();
}
catch (Exception ex)
{
error = ex;
}
}, null); }, null);
if (error != null) { Rethrow(error); }
} }
} }
/// <summary>
/// Rethrows the specified excetion while keeping stack trace.
/// </summary>
/// <param name="ex">The ex.</param>
protected static void Rethrow(Exception ex)
{
typeof(Exception).GetMethod("PrepForRemoting",
BindingFlags.NonPublic | BindingFlags.Instance)?.Invoke(ex, new object[0]);
throw ex;
}
internal void ThrowInvalidOp() internal void ThrowInvalidOp()
{ {
throw new InvalidOperationException(InvalidMessage); throw new InvalidOperationException(InvalidMessage);