Tôi đang gặp phải tình huống trong đó cuộc gọi PInvoke tới CloseHandle
đang ném SEHException
trong ứng dụng .NET 4 khi chạy trong trình gỡ lỗi. Không giống như others who have encountered similar issues migrating from 3.5 to 4, tôi không đặc biệt bị làm phiền bởi hành vi và đã xác định được sự cố (thư viện của bên thứ ba gọi số CloseHandle
hai lần trên cùng một tay cầm). Tuy nhiên, tôi lúng túng là tại sao hành vi này không xảy ra trong một ứng dụng .NET 3.5.Tại sao việc xử lý ngoại lệ từ CloseHandle khác nhau giữa .NET 4 và 3.5?
sau Ví dụ nhỏ nhưng đầy đủ chứng minh hành vi của tôi đang gặp (thử nghiệm trên cả XP SP3 và Win 7 x64, luôn biên soạn như 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);
}
Khi chạy như một ứng dụng .NET 4, an SEHException
được ném tại số CloseHandle
thứ hai. hành vi theo documentation for CloseHandle
, điều này được mong đợi:
Nếu ứng dụng đang chạy dưới một trình gỡ lỗi, hàm sẽ ném một ngoại lệ nếu nó nhận được một trong hai giá trị xử lý mà không là hợp lệ hay một giá trị giả xử lý . Điều này có thể xảy ra nếu bạn đóng một handle hai lần, hoặc nếu bạn gọi CloseHandle trên một tay cầm được trả về bởi hàm FindFirstFile thay vì gọi hàm FindClose.
Tuy nhiên, khi biên soạn như một ứng dụng .NET 3.5 (hoặc CLR 2.0), không có ngoại lệ được ném vào thứ hai CloseHandle
cuộc gọi, và thông điệp "No exception"
được in ra.
Theo this article, CLR được cập nhật phát hành cho .NET 4 có một số hành vi mặc định khác nhau với các ngoại lệ cấp thấp có khả năng làm hỏng trạng thái quy trình. Tuy nhiên, theo như tôi có thể hiểu từ bài viết đó, không có gì được đề cập đến trong hành vi CLR trước đó sẽ khiến cho ngoại lệ bị bỏ qua hoàn toàn.
Tại sao ứng dụng .NET 3.5 (hoặc CLR 2.0) không thể hiện hành vi được ghi lại là CloseHandle
có trong .NET 4?
Tôi rất vui vì MS đã thực hiện một số cải tiến trong đấu trường này. Tôi gặp khó khăn với các vấn đề ở đây cho các lứa tuổi: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/b5b7a179-3737-4380-b6cf-843f3e71b317/ – Brannon
Có lẽ trong pre .NET 4 chúng là chỉ cần im lặng bắt và bỏ qua những ngoại lệ đó –
Đó chính là điều tôi quan tâm để tìm ra - tại sao có thể là như vậy :) – jeffora