Sto riscontrando una situazione in cui una chiamata PInvoke a CloseHandle
sta lanciando un SEHException
in un'applicazione .NET 4 quando viene eseguita con un debugger. A differenza di others who have encountered similar issues migrating from 3.5 to 4, non sono particolarmente disturbato dal comportamento e ho già individuato il problema (una libreria di terze parti che chiama lo CloseHandle
due volte sullo stesso handle). Tuttavia, sono perplesso sul motivo per cui questo comportamento non si verifica in un'applicazione .NET 3.5.Perché la gestione delle eccezioni da CloseHandle è diversa tra .NET 4 e 3.5?
Il seguente esempio piccolo ma completo illustrato il comportamento che sto vivendo (testato sia su XP SP3 e Windows 7 x64, sempre compilato come x86):
class Program
{
static void Main(string[] args)
{
try
{
var hFileMapping = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04 /* read write */, 0, 0x1000, null);
CloseHandle(hFileMapping);
CloseHandle(hFileMapping);
Console.WriteLine("No exception");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpAttributes, int flProtect, int dwMaximumSizeHigh, int dwMaximumSizeLow, string lpName);
[DllImport("kernel32", SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);
}
Quando viene eseguito come un'applicazione .NET 4, un SEHException
viene lanciato al secondo CloseHandle
. comportamento Come per la documentation for CloseHandle
, questo è previsto:
Se l'applicazione è in esecuzione in un debugger, la funzione un'eccezione se riceve un valore maniglia che non è valido o un valore pseudo-handle . Ciò può accadere se si chiude un handle due volte o se si chiama CloseHandle su un handle restituito dalla funzione FindFirstFile anziché chiamare la funzione FindClose.
Tuttavia, se compilato come un'applicazione .NET 3.5 (o CLR 2.0), non viene generata un'eccezione alla seconda CloseHandle
chiamata e il messaggio "No exception"
viene stampato.
In base a this article, il CLR aggiornato rilasciato per .NET 4 presenta un comportamento predefinito diverso con eccezioni di basso livello che possono potenzialmente danneggiare lo stato del processo. Tuttavia, per quanto posso capire da quell'articolo, non c'è nulla di menzionato nel precedente comportamento CLR che possa far ignorare completamente l'eccezione.
Perché un'applicazione .NET 3.5 (o CLR 2.0) non presenta il comportamento documentato di CloseHandle
presente in .NET 4?
Io per parte sono contento che MS abbia apportato alcuni miglioramenti in questa arena. Ho faticato con i problemi qui da anni: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/b5b7a179-3737-4380-b6cf-843f3e71b317/ – Brannon
Forse in pre. NET 4 erano catturare e ignorare silenziosamente tali eccezioni –
Che è esattamente quello che mi interessa scoprire - perché potrebbe essere il caso :) – jeffora