У меня также есть приложение, которое использует как можно больше бара. У вас есть пара вариантов в зависимости от вашего конкретного сценария (у всех есть недостатки).
Одним из простейших является предварительное распределение кругового буфера классов (или байтов), которые вы кешируете, чтобы потреблять все фронты фронтов. Обычно это не является предпочтительным, потому что потребление всей ОЗУ на ящике, когда вам не нужно, является просто грубым.
Другой способ обработки больших кешей (или избежать исключений из памяти) заключается в том, чтобы сначала проверить, что память, которая мне нужна, существует до выделения. Это имеет недостаток в необходимости сериализации распределения памяти. В противном случае время между доступной оперативной памятью и выделением из ОЗУ может закончиться.
Вот образец наилучшим образом я нашел, чтобы сделать это в .NET:
//Wait for enough memory
var temp = new System.Diagnostics.PerformanceCounter("Memory", "Available MBytes");
long freeMemory = Convert.ToInt64(temp.NextValue()) * (long)1000000;
long neededMemory = (long)bytesToAllocate;
int attempts=1200; //two minutes
while (freeMemory < neededMemory)
{
//Signal that memory needs to be freed
Console.WriteLine("Waiting for enough free memory:. Free Memory:" + freeMemory + " Needed Memory(MB):" + neededMemory);
System.Threading.Thread.Sleep(100);
freeMemory = Convert.ToInt64(temp.NextValue()) * (long)1000000;
--attempts;
if (0 == attempts)
throw new OutOfMemoryException("Could not get enough free memory. File:" + Path.GetFileName(wavFileURL));
}
//Try and allocate the memory we need.
Кроме того, как только я нахожусь внутри цикла в то время как я сигнализировать, что некоторый объем памяти должен быть освобожден (в зависимости от вашего заявление). ПРИМЕЧАНИЕ. Я попытался упростить код, используя оператор Sleep, но в конечном итоге вам понадобится какой-то тип операции без опроса, если это возможно.
Я не уверен в специфике вашего приложения, но если вы многопоточны или запускаете много разных исполняемых файлов, то может быть лучше сериализовать эту проверку памяти при выделенной памяти в кеш. Если это так, я использую Семафор, чтобы убедиться, что только один поток и/или процесс могут выделять ОЗУ по мере необходимости. Подобно этому:
Semaphore namedSemaphore = new Semaphore(1, 1, "MemoryAllocationSemaphore"); //named semaphores are cross process
if (bytesToAllocate > 2000000) //if we need less than 2MB then dont bother locking.
{
if (!namedSemaphore.WaitOne((int)TimeSpan.FromMinutes(15).TotalMilliseconds))
{
throw new TimeoutException("Waited over 15 minutes for aquiring memory allocation semaphore");
}
}
Затем немного позже по вызову это:
namedSemaphore.Release();
в финальном блоке, чтобы освободить семафор.
Другой вариант заключается в использовании блокировки с одним считывателем нескольких считывателей.Чтобы несколько потоков вытягивали данные из кеша (например, класс ReaderWriterLock). Это имеет то преимущество, что, когда вы пишете, чтобы проверить давление и очистку памяти, добавьте еще больше в кеш, но все еще имеете несколько потоков обработки данных. Недостатком, конечно же, является то, что шейка бутылки для получения данных в кеш поступает из одной фиксированной точки.
проверить этот ответ: http://stackoverflow.com/a/1248141/941243 – Chris