Scrittura simultanea di file tra processi

Ho bisogno di scrivere i dati del registro in un singolo file da processi diversi.

Sto usando Windows Mutex che richiede il supporto Common Language Runtime per questo.

Mutex^ m = gcnew Mutex( false,"MyMutex" ); m->WaitOne(); //... File Open and Write .. m->ReleaseMutex() 

Devo davvero passare da C ++ a C ++ / CLI per la sincronizzazione?

Va bene se l’atomico non è usato. Ma ho bisogno di sapere se l’utilizzo di questo Mutex rallenterà le prestazioni rispetto al mutex locale.

L’aggiunta del supporto CLR all’applicazione C ++ solo per ottenere la class Mutex è eccessiva. Sono disponibili diverse opzioni per sincronizzare l’accesso ai file tra due applicazioni.

Opzione 1: Mutex

Se hai bisogno di scrivere un file da più processi, usare un mutex è un buon modo per farlo. Utilizzare le funzioni mutex nell’API Win32. (La class .Net Mutex è comunque solo un wrapper attorno a tali funzioni.)

 HANDLE mutex = CreateMutex(NULL, false, "MyMutex"); DWORD waitResult = WaitForSingleObject(mutex, INFINITE); if (waitResult == WAIT_OBJECT_0) { // TODO: Write the file WriteFile(...); ReleaseMutex(mutex); } 

Come indicato nell’altra risposta, dovrai aprire il file con la condivisione, in modo che entrambe le applicazioni possano aprirlo contemporaneamente. Tuttavia, questo di per sé potrebbe non essere sufficiente: se entrambe le tue applicazioni stanno cercando di scrivere nella stessa area del file, dovrai comunque assicurarti che scriva solo un’applicazione alla volta. Immaginate se entrambe le applicazioni guardino le dimensioni del file, quindi entrambi provano a scrivere contemporaneamente a quell’offset di byte: anche se entrambi hanno cercato di accodarsi alla fine del file, hanno finito per clobbering l’un l’altro.

Opzione 2: Apri solo come append

Se stai scrivendo semplicemente alla fine del file, e non stai mai tentando di leggere nulla o scrivere da qualche altra parte oltre la fine del file, allora c’è una modalità speciale che puoi usare che ti permetterà di non usare un mutex . Se apri il file con dwDesiredAccess impostato su FILE_APPEND_DATA | SYNCHRONIZE FILE_APPEND_DATA | SYNCHRONIZE e nient’altro (non includere FILE_WRITE_DATA ), quindi il sistema operativo si prenderà cura di assicurarsi che tutti i dati che vengono scritti sul file alla fine e le due applicazioni che scrivono i dati non si sovrascrivano l’un l’altro. Questo comportamento è documentato su MSDN :

Se sono impostati solo i flag FILE_APPEND_DATA e SYNCHRONIZE, il chiamante può scrivere solo alla fine del file e qualsiasi informazione di offset relativa alle scritture sul file viene ignorata. Tuttavia, il file verrà automaticamente esteso, se necessario, per questo tipo di operazione di scrittura.

Opzione 3: LockFile

Un altro percorso che puoi fare è usare il metodo LockFile . Con LockFile (o LockFileEx ), è ansible avere entrambe le applicazioni per aprire il file e fare in modo che ogni app blocchi la sezione del file in cui desidera scrivere. Questo ti dà più granularità rispetto al mutex, permettendo che le scritture non sovrapposte si verifichino contemporaneamente. (L’uso di LockFile sull’intero file ti darà lo stesso effetto di base del mutex, con l’ulteriore vantaggio che impedirà ad altre applicazioni di scrivere il file mentre lo fai.) C’è un buon esempio di come usare LockFile Il blog di Raymond Chen .

In realtà non è necessario usare un mutex separato, puoi semplicemente usare il file stesso. Quando un file viene aperto con la chiamata API CreateFile (consultare https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 ), la chiamata accetta un parametro chiamato dwShareMode che specifica quale accesso simultaneo è consentito da altri processi. Un valore pari a 0 impedirebbe ad altri processi di aprire completamente il file.

Praticamente tutte le API per aprire una mappa di file in CreateFile sono sotto il cofano, quindi clr potrebbe fare la cosa giusta per te quando apri un file per scrivere già.

Nel runtime C c’è anche _fsopen che ti permette di aprire un file con i flag di condivisione.

Ti consigliamo di verificare quale sia la modalità di condivisione predefinita quando apri il tuo file da C #. Se non impedisce l’apertura simultanea per la scrittura di default, usa _fsopen da C (o forse c’è una funzione C # appropriata).