Как утилизировать систему.Рисование.Шрифт в параллельной потоковой передаче?

#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. Как я и сказал: начните со схемы именования, которая позволяет вам создавать уникальное имя (строку) для каждого шрифта / варианта, который вам нужен, скажем, фамилия Размер атрибуты… Затем словарь для хранения шрифтов с именем, которое вы создали в качестве ключа. Он должен быть доступен для каждого из ваших потоков, и если ключ уже есть, вы можете использовать шрифт, в противном случае добавьте его. Вам нужно будет позаботиться о блокировке, но в противном случае каждый шрифт будет создан и сохранен только один раз..