2013-02-14 6 views
1

У меня есть два приложения .NET 4.0 WinForms, которые (в первую очередь) читают географические данные из общих MemoryMappedFiles. Конечный пользователь может запускать одно из приложений или другое или запускать оба одновременно. Первое приложение, которое открывается, создает имя MemoryMapFile-s, второе открывает уже существующие. Однако открытие существующего имени MemoryMappedFile кажется ненадежным. Он работает примерно в 80% случаев, но около 20% случаев он терпит неудачу с FileNotFoundException. Симптом не безопасно воспроизводится, кажется, что это просто удача, когда он терпит неудачу, и когда это удается.Неудовлетворительное подключение к MemoryMappedFile

Вот код, используемый как приложения, чтобы получить MemoryMappedFiles:

private static MemoryMappedFile GetMemoryMappedFile(string filePath) 
{ 
    string mapName = filePath; // I have also tried here @"Global\myfile", no difference 
    MemoryMappedFile mmf = null; 
    try 
    { 
     // When the first app executes this step, it always succeeds. 
     // When the second app comes here, it fails as it should. 
     mmf = MemoryMappedFile.CreateFromFile(filePath, FileMode.OpenOrCreate, 
           mapName, HundredMB, MemoryMappedFileAccess.ReadWrite); 
    } 
    catch (IOException) 
    { 
     try 
     { 
      // Opening the already existing named MemoryMappedFile by the SECOND app. 
      // This line fails about 20% of the time. 
      mmf = MemoryMappedFile.OpenExisting(mapName, 
            MemoryMappedFileRights.ReadWrite); 
     } 
     catch (FileNotFoundException ex) 
     { 
      Console.WriteLine("Yet again, could not open MMF. Life sux."); 
     } 
    } 
    return mmf; 
} 

ответ

0

Я являюсь автором вопроса, и я дурак. MMF работает так, как предполагалось. Ошибки были вызваны вторым методом (написанным мной совсем некоторое время назад), где я создаю MMF-ы, но я применил там другие соглашения об именах MMF. Код в вопросе не сработал (правильно), потому что некоторые из MMF-файлов были созданы во втором методе под неправильными именами.

Я не удаляю вопрос, потому что по-прежнему есть ценные ответы, внесенные, которые могут помочь позже читателям. Большое спасибо за всех, кто нашел время ответить.

2

Что вы описали кажется вполне вероятным случай. У вас есть состояние гонки. Например, код, который генерирует исключение в CreateFromFile, сообщает вам, что файл существует. Затем другой процесс закрывает файл до того, как этот код достигнет OpenExisting. Затем вызывается OpenExisting, потому что файл больше не существует. Это действительный случай, когда вам нужно написать код.

+0

Хотя вы технически верны, это вряд ли является реальной проблемой. Приложения создают/открывают MMF, когда они запускают и закрывают их только тогда, когда они убиты. Кроме того, приложения работают круглосуточно. Всегда второй терпит неудачу, когда он открывается. – user256890

+0

Ну, вы действительно не предоставили никакой информации, чтобы предположить, что ваш код не виноват и что.Внедрение NET Framework в MemoryMappedFile либо ошибочно, либо не документировано правильно. Все, что вы описали, предполагает, что у вас есть состояние гонки больше всего на свете. –

+0

Попробуйте использовать 'File.Exists', чтобы увидеть, возвращает ли он' false', когда происходит 'FileNotFoundException'. Это еще одно условие гонки; но он должен быть «ложным» больше, чем «истина» с 20% -ой неудачей, если ваша проблема действительно является условием гонки. Если это всегда 'истина', то да, у вас, вероятно, нет условия гонки в вашем коде. –

1

Как насчет переворота вокруг логики? Поскольку создание MMF должно быть одноразовым, но открытие существующего должно быть более часто случаем, может быть, это сработает?

private static MemoryMappedFile GetMemoryMappedFile(string filePath) 
{ 
    var mapName = filePath; // I have also tried here @"Global\myfile", no difference 
    MemoryMappedFile mmf = null; 

    try 
    { 
     // When the first app executes this step, it fails as it should. 
     // Opening the already existing named MemoryMappedFile by the SECOND app. 
     mmf = MemoryMappedFile.OpenExisting(mapName, MemoryMappedFileRights.ReadWrite); 
    } 
    catch (FileNotFoundException) 
    { 
     try 
     { 
      // When the first app executes this step, it always succeeds. 
      mmf = MemoryMappedFile.CreateFromFile(
       filePath, 
       FileMode.OpenOrCreate, 
       mapName, 
       HundredMB, 
       MemoryMappedFileAccess.ReadWrite); 
     } 
     catch (IOException ex) 
     { 
      Console.Error.WriteLine("Yet again, could not open MMF. Life sux: " + ex); 
     } 
    } 

    return mmf; 
} 
+0

Я также заметил, что если я использовал '@" Global \ myfile "для' mapName', я должен был запускаться как Администратор, иначе я получил бы «UnauthorizedAccessException». –

3
string mapName = filePath; 

Это выглядит довольно принципиально тусклый. Строка filePath должна всегда ссылаться на абсолютный путь к файлу. Как «c: \ foo \ bar \ baz.bin», никогда не относительное имя файла, например «baz.bin». Имя типа «Global \ myfile» не является именем пути, это имя карты памяти. Это то, что другой процесс использует для открытия отображения, он не знает или не заботится о фактическом файле, который действует как хранилище резервных копий для карты.

Очень распространенный способ, которым это не удастся, - это когда рабочий каталог вашей программы (Environment.CurrentDirectory) не установлен там, где вы надеетесь, что он установлен. У него есть умение меняться без вашего осознания, кроме того, что внезапно происходит сбой вызова CreateFromFile().

Так что устраните проблему, выбрав уникальное имя карты, которое очень специфично для вашего приложения. И файл, который вы выбираете с полным именем пути. Обычно хранится в AppData, папке, в которой у вас есть доступ на запись без повышения UAC.

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

  • Нет связанных вопросов^_^