#c# #memory-leaks #dispose #system.drawing
#c# #утечки памяти #утилизировать #system.drawing
Вопрос:
Мы генерируем 1000 аудиторских отчетов в час, используя параллельные потоки. Во время генерации мы используем Систему.Рисование.Шрифт для записи текста в PDF-файлы (syncfusion). Поскольку нам нужно использовать разные шрифты (8-10 типов) для каждого аудита, это приводит к заметному увеличению объема памяти на рабочем сервере. Чтобы избежать этого, мы попытались удалить их после сохранения каждого PDF-файла в поток памяти.
using (var loadedDocument = new PdfDocument())
{
var indexPage = loadedDocument.Pages.Add();
var header = indexPage.Graphics;
var calibri35Font = new Font("Calibri", 35);
var calibri35PdfFont = new PdfTrueTypeFont(calibri35Font);
var stringCenterFormat = new PdfStringFormat { Alignment = PdfTextAlignment.Center };
header.DrawString("AUDIT REPORT n", calibri35PdfFont, PdfBrushes.Black, new PointF(250, 50), stringCenterFormat);
--------
--------
--------
using (var stream = new MemoryStream())
{
loadedDocument.Save(stream);
}
calibri35Font.Dispose();
calibri35PdfFont.Dispose();
}
Однако это вызывает проблемы с нулевым исключением из-за того, что параллельные потоки пытаются загрузить один и тот же шрифт.
Вопрос в том, как безопасно утилизировать шрифты, не нарушая параллельные процессы, использующие один и тот же ресурс, и есть ли лучший способ решить проблемы с памятью.
Комментарии:
1. Вы можете использовать
using( var calibri35Font = new Font("Calibri", 35))
, чтобы не вызывать dispose your self. Но я пойду другим путем, не утилизируйте шрифт. Никогда. Спрячьте их где-нибудь и заблокируйте, когда вы их используете.2. Используете ли вы один и тот же объект шрифта в нескольких потоках? В вашем примере не показано никакой многопоточности, и я бы ожидал, что создание, использование и удаление шрифта будет безопасным, если все это выполняется в одном потоке.
3. Я бы все равно попытался создать «кэш шрифтов»; Он может быть настолько большим, насколько вам нужно, если вы повторно используете уже имеющиеся шрифты. Схема именования и словарь <строка, шрифт> могут выполнить эту работу..
4. Спасибо за ответ @TaW, не могли бы вы, пожалуйста, предоставить мне пример того, как создать кэш шрифтов
5. Как я и сказал: начните со схемы именования, которая позволяет вам создавать уникальное имя (строку) для каждого шрифта / варианта, который вам нужен, скажем, фамилия Размер атрибуты… Затем словарь для хранения шрифтов с именем, которое вы создали в качестве ключа. Он должен быть доступен для каждого из ваших потоков, и если ключ уже есть, вы можете использовать шрифт, в противном случае добавьте его. Вам нужно будет позаботиться о блокировке, но в противном случае каждый шрифт будет создан и сохранен только один раз..