4

次のようにメモリマップファイルを作成するコードがあります。

using (Mutex mutex = new Mutex(false, CoordinatorMutexName))
{
    mutex.WaitOne();

    var security = new MemoryMappedFileSecurity();
        security.SetAccessRule(
            new AccessRule<MemoryMappedFileRights>(
                new SecurityIdentifier(WellKnownSidType.WorldSid, null), // everyone
                MemoryMappedFileRights.FullControl,
                AccessControlType.Allow));

    MemoryMappedFile coordinator = MemoryMappedFile.CreateOrOpen(
        CoordinatorMMFName,
        16 * 1024 * 1024 + 4,
        MemoryMappedFileAccess.ReadWrite,
        MemoryMappedFileOptions.DelayAllocatePages,
        security,
        HandleInheritability.None);

...
...

}

特定の状況 (後述) では、CreateOrOpen 呼び出しで次の例外がスローされます。

 System.IO.IOException: The handle is invalid.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.MemoryMappedFiles.MemoryMappedFile.CreateOrOpenCore(SafeFileHandle fileHandle, String mapName, HandleInheritability inheritability, MemoryMappedFileSecurity memoryMappedFileSecurity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, Int64 capacity)
   at System.IO.MemoryMappedFiles.MemoryMappedFile.CreateOrOpen(String mapName, Int64 capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability)

自動テストの実行中にのみこの例外がスローされます。デバッガーの内部または外部でこれをローカルで再現することはできません。上記のコードだけをスタンドアロン テストに抽出しようとしましたが、問題を再現できませんでした。しかし、ここにすべてを掲載するにはコードが多すぎます。MemoryMappedFile は、スレッドの存続期間中保持され (作成されると仮定)、その後破棄されます。

テストが失敗する条件は次のとおりです。 テストは、複数のスレッドからこのコードを実行するように設計されています。それらは NUnit 内にあり、CruiseControl.NET の下で実行され、そのサービスは 64 ビット Windows 2008 Server 上のドメイン アカウント (ローカル マシン アカウントではない) の下で実行されます。同じマシンにログインしているときに同じテストを手動で実行でき、すべて合格です。

誰かが直接解決するにはおそらく十分な情報ではないことはわかっていますが、この問題を調査する方法さえ失っています。メモリ マップされたファイルを CreateOrOpen しようとすると、どのようなことが原因で「ハンドルが無効です」というメッセージが表示される可能性がありますか?

4

1 に答える 1

4

メモリ マップされたファイルを作成する基になる winapi 関数である CreateFileMapping() のエラー コードが文書化されています。

lpName が既存のイベント、セマフォ、ミューテックス、待機可能なタイマー、またはジョブ オブジェクトの名前と一致する場合、関数は失敗し、GetLastError 関数は ERROR_INVALID_HANDLE を返します。これは、これらのオブジェクトが同じ名前空間を共有するために発生します。

したがって、このエラーを回避するために適切なランダムな名前を選択してください。Visual Studio から取得できます: ツール + GUID の作成、オプション 4。これはグローバルに一意です。

于 2012-04-17T18:44:38.203 に答える