Zdaję się sytuacji, w której wywołanie PInvoke do CloseHandle
rzuca SEHException
w aplikacji .NET 4, gdy jest uruchomiony w debugerze. W przeciwieństwie do others who have encountered similar issues migrating from 3.5 to 4, nie jestem szczególnie zaniepokojony tym zachowaniem i już zlokalizowałem problem (trzecia strona biblioteki wywołująca dwa razy na tym samym uchwycie). Jednak jestem zakłopotany, dlaczego to zachowanie nie występuje w aplikacji .NET 3.5.Dlaczego obsługa wyjątków z programu CloseHandle różni się między platformami .NET 4 i 3.5?
Poniżej mały, ale kompletny przykład demonstruje zachowanie mam przeżywa (testowane zarówno na XP SP3 i Win 7 x64, zawsze kompilowany jako 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);
}
gdy uruchamiane jako aplikacja .NET 4, SEHException
jest wyrzucane na drugim CloseHandle
. Zgodnie z documentation for CloseHandle
, spodziewane jest zachowanie:
Jeśli aplikacja działa pod debugera funkcja wyjątek, jeżeli odbiera zarówno wartość uchwyt nie jest ważne lub wartości pseudo uchwytu . Może się to zdarzyć, jeśli dwa razy zamkniesz uchwyt lub jeśli wywołasz CloseHandle na uchwycie zwróconym przez funkcję FindFirstFile zamiast wywoływać funkcję FindClose.
Jednakże, kiedy zestawiane jako NET 3,5 aplikacji (lub CLR 2,0), nie jest wyjątek w drugim CloseHandle
połączenia i komunikat "No exception"
wydrukowaniu.
Zgodnie z this article, zaktualizowana wersja CLR wydana dla .NET 4 ma inne domyślne zachowanie z wyjątkami niskiego poziomu, które mogą uszkodzić stan procesu. Jednak, o ile mogę zrozumieć z tego artykułu, nie ma nic wspominanego o poprzednim zachowaniu CLR, które spowodowałoby całkowite zignorowanie tego wyjątku.
Dlaczego aplikacja .NET 3.5 (lub CLR 2.0) nie wykazuje udokumentowanego zachowania CloseHandle
obecnego w .NET 4?
Po pierwsze cieszę się, że MS dokonało pewnych ulepszeń na tej arenie. Od lat borykałem się z problemami: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/b5b7a179-3737-4380-b6cf-843f3e71b317/ – Brannon
Może w wersji .NET 4 były po cichu łapie i ignoruje te wyjątki –
Co jest dokładnie tym, co mnie interesuje, aby dowiedzieć się - dlaczego tak być może jest :) – jeffora