Torna al Thread
enum AllocationType
{
MEM_COMMIT = 0x1000,
MEM_RESERVE = 0x2000,
MEM_RESET = 0x8000
}
enum DeallocationType
{
MEM_RELEASE = 0x8000
}
enum MemoryProtection
{
PAGE_READONLY = 0x02,
PAGE_READWRITE = 0x04
}
[DllImport("kernel32.dll")]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, int dwSize, AllocationType fAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll")]
static extern bool VirtualFree(IntPtr lpAddress, int dwSize, DeallocationType dwFreeType);
struct SharedData
{
public int v1;
public bool v2;
public char v3;
public Point v4;
//Non puoi inserire delle variabili di tipo classe
//perchè sono dei tipi di riferimento, e non
//hanno senso nella memoria esterna
}
//Il contenuto di questo puntatore indica la necessità
//di aggiornare i dati inseriti da un processo esterno
unsafe bool* mustRefresh = null;
//Questo è l'indirizzo della memoria dove scrivere i dati correnti
IntPtr sharedMemPtr = IntPtr.Zero;
//Questo è l'indirizzo della memoria dove gli altri processi scrivono
//i nuovi dati per eseguire l'aggiornamento di quelli correnti
IntPtr refreshPtr = IntPtr.Zero;
//questi sono i dati che vengono elaborati da questo processo
int data1;
bool data2;
char data3;
Point data4;
//Questa è la struttura che viene usata per scrivere e leggere i
//dati sulla e dalla memoria condivisa
SharedData data;
//Questa funzione inizializza la memoria condivisa
unsafe IntPtr InitSharedMem()
{
//Ottiene il numero di byte necessari a contenere la struttura
//dei dati condivisi
int byteCount = Marshal.SizeOf(typeof(SharedData));
//Alloca della memoria con accesso sia in lettura che in scrittura,
//di dimensioni sufficienti a contenere i dati significativi
sharedMemPtr = VirtualAlloc(IntPtr.Zero, //Il sistema sceglie l'indirizzo di allocazione
byteCount, //Il numero di byte da allocare
AllocationType.MEM_RESERVE | AllocationType.MEM_COMMIT, //riserva la memoria e la alloca
MemoryProtection.PAGE_READWRITE); //permette la lettura e la scrittura
//Alloca un bool nella memoria condivisa che viene usato per indicare
//se l'applicazione deve aggiornare i dati
mustRefresh = (bool*)VirtualAlloc(IntPtr.Zero,
sizeof(bool),
AllocationType.MEM_RESERVE | AllocationType.MEM_COMMIT,
MemoryProtection.PAGE_READWRITE).ToPointer();
*mustRefresh = false;
//Alloca della memoria con accesso in lettura e in scrittura,
//che viene usata per ricevere i nuovi parametri per l'aggiornamento
refreshPtr = VirtualAlloc(IntPtr.Zero,
byteCount,
AllocationType.MEM_COMMIT | AllocationType.MEM_RESERVE,
MemoryProtection.PAGE_READWRITE);
//Crea una chiave di registro dove scrivere l'indirizzo della memoria condivisa
//e l'ID del processo da cui leggerla, serve alle applicazioni esterne per interagire
RegistryKey swKey = Registry.LocalMachine.CreateSubKey("Software");
RegistryKey infoKey = swKey.CreateSubKey("SharedMemTest");
infoKey.SetValue("MemPtr", (int)sharedMemPtr, RegistryValueKind.DWord);
infoKey.SetValue("ProcessID", Process.GetCurrentProcess().Id, RegistryValueKind.DWord);
//Scrive nel registro l'indirizzo in memoria del valore da impostare
//Per richiedere l'aggiornamento dei dati
infoKey.SetValue("MustRefreshPtr", (int)mustRefresh, RegistryValueKind.DWord);
//Scrive nel registro l'indirizzo della memoria condivisa dove inserire
//i nuovi dati per il refresh
infoKey.SetValue("NewDataPtr", (int)refreshPtr);
//Chiude le chiavi di registro
infoKey.Close();
swKey.Close();
//Ottiene l'indirizzo della memoria condivisa
return sharedMemPtr;
}
//Questa funzione elabora i dati correnti
void Elabora()
{
//Controlla se i dati devono essere aggiornati
unsafe
{
if (*this.mustRefresh)
{
//Se sì, esegue l'aggiornamento: ottiene i nuovi dati dalla memoria condivisa
this.data = (SharedData)Marshal.PtrToStructure(this.refreshPtr, typeof(SharedData));
//Aggiorna tutti i valori
this.data1 = data.v1;
this.data2 = data.v2;
this.data3 = data.v3;
this.data4 = data.v4;
//Non è più necessario eseguire l'aggiornamento
*mustRefresh = false;
}
}
//Elabora i valori
this.data1 += this.data4.X;
this.data2 = !this.data2;
this.data3 = (char)(data4.Y & 0xFF);
this.data4.X++;
this.data4.Y++;
//Imposta i valori elaborati nella struttura
this.data.v1 = data1;
this.data.v2 = data2;
this.data.v3 = data3;
this.data.v4 = data4;
//Scrive i valori nella memoria condivisa
Marshal.StructureToPtr(this.data, this.sharedMemPtr, false);
}
void CleanUp()
{
//Elimina i registri di sistema usati
RegistryKey swKey = Registry.LocalMachine.CreateSubKey("Software");
swKey.DeleteSubKeyTree("SharedMemTest");
swKey.Close();
//Dealloca la memoria condivisa non gestita
VirtualFree(this.sharedMemPtr, 0, DeallocationType.MEM_RELEASE);
unsafe
{
IntPtr refrPtr = new IntPtr(this.mustRefresh);
VirtualFree(refreshPtr, 0, DeallocationType.MEM_RELEASE);
}
VirtualFree(refreshPtr, 0, DeallocationType.MEM_RELEASE);
}