2015-05-17 2 views
1

Почему один и тот же код в .Net (C#) висит, но в C++ это не так? Действительно проблема заключается в System.IO.FileStream, но я уменьшил его до CreateFile, тем не менее, он все еще висит в .Net (в то же время почти 100% аналог C++ кода):Почему .NET-версия зависает, но C++ нет?

using System; 
using System.Runtime.InteropServices; 
using System.Threading; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static IntPtr _handle; 

     static void Main() 
     { 
      _handle = CreateFile("test.txt", GENERIC_READ | GENERIC_WRITE, 
       FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, 
       OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero); 

      new Thread(MyProc) { IsBackground = true }.Start(); 
      new Thread(MyProc) { IsBackground = true }.Start(); 

      Console.ReadKey(); 
     } 

     static void MyProc() 
     { 
      for (int i = 0; i < int.MaxValue; i++) 
      { 
       Console.WriteLine(i); 

       var _overlapped = new NativeOverlapped(); 

       LockFileEx(_handle, LOCKFILE_EXCLUSIVE_LOCK, 0, int.MaxValue, int.MaxValue, ref _overlapped); 

       Thread.Sleep(50); 

       UnlockFileEx(_handle, 0, int.MaxValue, int.MaxValue, ref _overlapped); 
      } 
     } 

     public const int LOCKFILE_EXCLUSIVE_LOCK = 0x00000002; 

     [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
     public static extern bool LockFileEx(IntPtr hFile, int flags, int reserved, int numberOfBytesToLockLow, int numberOfBytesToLockHigh, 
      ref NativeOverlapped overlapped); 

     [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
     public static extern bool UnlockFileEx(IntPtr hFile, int reserved, int numberOfBytesToUnlockLow, int numberOfBytesToUnlockHigh, 
      ref NativeOverlapped overlapped); 

     public const int GENERIC_READ = unchecked((int)0x80000000L); 
     public const int GENERIC_WRITE = (int)0x40000000L; 

     public const int OPEN_ALWAYS = 4; 

     public const int FILE_SHARE_READ = 0x00000001; 
     public const int FILE_SHARE_WRITE = 0x00000002; 
     public const int FILE_SHARE_DELETE = 0x00000004; 

     public const int FILE_ATTRIBUTE_NORMAL = 0x00000080; 

     [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
     public static extern IntPtr CreateFile(string fileName, int desiredAccess, int shareMode, 
      IntPtr pSecurityAttributes, int creationDisposition, int flagsAndAttributes, IntPtr hTemplateFile); 
    } 
} 

А вот C++ версия которые не висят:

#include "stdafx.h" 

#include <thread> 
#include <Windows.h> 

HANDLE hFile; 

DWORD WINAPI MyProc(LPVOID lpParam); 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    hFile = CreateFile(L"test.txt", GENERIC_READ | GENERIC_WRITE, 
     FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 
     OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 

    HANDLE hThread1 = CreateThread(NULL, 0, MyProc, NULL, 0, NULL); 
    HANDLE hThread2 = CreateThread(NULL, 0, MyProc, NULL, 0, NULL); 

    int ch = getchar(); 

    return 0; 
} 

DWORD WINAPI MyProc(LPVOID lpParam) 
{ 
    for(int i = 0; i < INT_MAX; i++) 
    { 
     printf("%d\r\n", i); 

     OVERLAPPED overlapped = {0}; 

     LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, INT_MAX, INT_MAX, &overlapped); 

     Sleep(50); 

     UnlockFileEx(hFile, 0, INT_MAX, INT_MAX, &overlapped); 
    } 

    return 0; 
} 
+2

Downvoters, объясните пожалуйста! – frtnum

+0

Кажется, что факт зависания зависит от чего-то в конфигурации. Мой такой: Net 4.5, VS 2012 Express, Win7 64bit, i7-3610QM. .Net вариант 100% с двумя нулями в консоли. Очень редко он идет до двух десятков, а затем все еще висит. – frtnum

+1

Вы пытались приостановить и проверить, где находится каждый поток, когда он зависает с помощью Debug-> Windows-> Threads? (Предполагая, что вы используете Visual Studio) –

ответ

-1

похоже, это недопустимое назвать LockFileEx с LOCKFILE_EXCLUSIVE_LOCK на тот же файл обрабатывать дважды. Для дескриптора это должны быть разные дескрипторы файлов или некоторая синхронизация в процессе.

Беспокойство заключается в том, что в документации MSDN нет однозначности в этом вопросе. И нет четкого сообщения об ошибке во время выполнения. Более того, мне кажется, что проблема воспроизводится только на моем компьютере. Это уродливо.

+0

Интересно, кто это проголосовал за это? Правильный ответ? Я уверен, что проблема заключается в вызове LockFileEx (LOCKFILE_EXCLUSIVE_LOCK) в одном и том же файле дважды (и более). Мой рабочий проект, поскольку я добавил синхронизацию в процессе между потоками совместного использования файлов, теперь работает стабильно. – frtnum

+0

Проблема заключается в том, что это должно быть четко указано в документации LockFileEx, а также для того, чтобы быть ясной ошибкой времени выполнения, а не вероятностью, но быть определена. – frtnum

Смежные вопросы