Получение ошибки в DrawString (C# WinForms)

Я работаю над WinFormsProject, все работает, но когда мне нужно распечатать счет, появляется это исключение

System.ArgumentException: Parameter is not valid.

   at System.Drawing.Graphics.CheckErrorStatus(Int32 status)

   at System.Drawing.Graphics.DrawString(String s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format)

   at Panaderia_Supabase.Forms.Cobranza.PrintPage(Object sender, PrintPageEventArgs e) in D:\Dev\Nueva carpeta\Panaderia-Supabase\Forms\Cobranza.cs:line 217

Эта ошибка появилась, когда я сделал метод асинхронным для работы с супабазой. Я проверил, что все значения не равны нулю. Я думаю проблема в графике:

В этом методе:

    public float GetHeight(Graphics graphics)
    {
        ArgumentNullException.ThrowIfNull(graphics, "graphics");
        if (graphics.NativeGraphics == IntPtr.Zero)
        {
            throw new ArgumentException("graphics");
        }
        SafeNativeMethods.Gdip.CheckStatus(SafeNativeMethods.Gdip.GdipGetFontHeight(new HandleRef(this, NativeFont), new HandleRef(graphics, graphics.NativeGraphics), out var size));
        return size;
    }

Это значение, когда я запускаю проект: Graphics.NativeGraphics = 0x0000024f04c04230

И когда я пытаюсь распечатать счет, он переходит к: Graphics.NativeGraphics = 0x0000000000000000

Это мой метод:

    private async void PrintPage(object sender, PrintPageEventArgs e)
      {
      try
        {
        // Verifica si el objeto Graphics es válido
        if (e.Graphics == null)
          {
          MessageBox.Show("Objeto Graphics no válido.");
          return;
          }

        Graphics graphics = e.Graphics;
        Font font = new("Courier Mono", 10, FontStyle.Regular);
        Brush brush = Brushes.Black;
        // Generar el ticket
        string ticket = await GenerateTicket();
        if (string.IsNullOrEmpty(ticket))
          {
          MessageBox.Show("El ticket no se ha generado correctamente.");
          return;
          }

        float yPos = 10;
        float xPos = 10;
        float lineHeight = font.Height;

        try
          {
          MessageBox.Show($"Altura de la línea: {lineHeight}");
          }
        catch (Exception ex)
          {
          MessageBox.Show($"Error al obtener la altura de la línea: {ex.Message}");
          return;
          }

        try
          {
          using (StringReader reader = new StringReader(ticket))
            {
            string line;
            while ((line = reader.ReadLine()) != null)
              {
              if (yPos + lineHeight <= e.MarginBounds.Bottom)
                {
                try
                  {
                  if (string.IsNullOrEmpty(line) || font == null || brush == null || xPos == 0 || yPos == 0)
                    {
                    MessageBox.Show($"Valor nulo: line - {line}, font - {font}, brush - {brush} , xPos - {xPos}, yPos - {yPos}");
                    }
                  else
                    graphics.DrawString(line, font, brush, xPos, yPos);
                  }
                catch (Exception ex)
                  {
                  MessageBox.Show($"{ex}");
                  return;
                  }
                yPos += lineHeight;
                }
              else
                {
                e.HasMorePages = true;
                return;
                }
              }
            }
          }
        catch (Exception ex)
          {
          MessageBox.Show($"Error durante el proceso de impresión: {ex.Message}");
          }

        graphics.Dispose();
        font.Dispose();
        brush.Dispose();
        e.HasMorePages = false;
        }
      catch (Exception ex)
        {
        MessageBox.Show($"Error en PrintPage: {ex.Message}");
        }
      }

Если вам нужен еще исходный код, просто попросите его, и я предоставлю. Спасибо!

Я проверил недействительность всех параметров, попытался передать фиксированные значения, поскольку параметры тоже не сработали. А сообщения об исключениях не очень полезны, поэтому я не знаю, что делать.

Я вижу одну интересную вещь: подпись метода — DrawString(String s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format), но вы передаете (string, Font, Brush, float, float). Как вы думаете, почему он вызывает это вместо метода, который вы ожидаете?

A N 17.07.2024 19:12

Первым делом удалите это: graphics.Dispose();. Это не копия, это фактическая ссылка на объект Graphics. Вы не избавляетесь от него. Это также бесполезно: Graphics graphics = e.Graphics;, но безвредно. После этого посмотрите, сможете ли вы вызвать GenerateTicket() до того, как будет сгенерировано событие PrintPage.

Jimi 17.07.2024 19:18

@AN Независимо от того, какую перегрузку DrawString() вы вызываете, в конце концов выполняется именно она.

Jimi 17.07.2024 19:19

Спасибо за помощь ребята. Я думаю, что на самом деле это произошло из-за асинхронного ожидания другого метода (GenerateTicket()). Я попробовал это с фиксированным значением в неасинхронном исполнении, и это сработало. Если это не сработает, я вернусь сюда

Lucas Rius 17.07.2024 20:07

Этот вид графической процедуры не должен быть асинхронным. Вы читали примечание о graphics.Dispose();? Вы не сможете этого сделать, никогда. Вы избавляетесь только от созданного вами объекта, а не от объектов, предоставленных инфраструктурой (подумайте о стандартных объектах, если это поможет).

Jimi 17.07.2024 21:41
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете использовать async void в обработчике PrintPage, потому что объект Graphics поступает от вызывающего объекта, и они распечатают документ и утилизируют его, как только вы вернетесь, что происходит в первый раз await. Таким образом, вам придется получить это значение где-то еще, прежде чем этот обработчик запустится.

Также:

  • Не выбрасывайте e.Graphics.
  • Утилизируйте font и brush с помощью using, если вы их создаете. Вам не нужно этого делать, если они уже существуют в системе, поскольку это не требуется.
  • Также можно существенно упростить логику:
    • Вам не нужно так много trycatch, снаружи можно использовать один.
    • Инвертирование некоторых if означает, что вы можете удалить else.
  • font, brush и e.Graphics не будут null, вам не нужно это проверять.
private void PrintPage(object sender, PrintPageEventArgs e)
{
    try
    {
        string ticket = GetAlreadyGeneratedTicket();    // you can't use async while using the Graphics
        if (string.IsNullOrEmpty(ticket))
        {
            MessageBox.Show("El ticket no se ha generado correctamente.");
            return;
        }

        Graphics graphics = e.Graphics;
        using Font font = new("Courier Mono", 10, FontStyle.Regular);
        Brush brush = Brushes.Black;

        float yPos = 10;
        float xPos = 10;
        float lineHeight = font.Height;

        MessageBox.Show($"Altura de la línea: {lineHeight}");

        using StringReader reader = new StringReader(ticket);
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            if (yPos + lineHeight > e.MarginBounds.Bottom)
            {
                e.HasMorePages = true;
                return;
            }

            if (string.IsNullOrEmpty(line) || xPos == 0 || yPos == 0)
            {
                MessageBox.Show($"Valor nulo: line - {line}, font - {font}, brush - {brush} , xPos - {xPos}, yPos - {yPos}");
            }
            else
                graphics.DrawString(line, font, brush, xPos, yPos);

            yPos += lineHeight;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Error durante el proceso de impresión: {ex.Message}");
    }

    e.HasMorePages = false;
}

Другие вопросы по теме