«InvalidOperationException: объект в настоящее время используется в другом месте» во время безвредного onpaint?

#c# #paint #invalidoperationexception

#c# #Краски #invalidoperationexception

Вопрос:

По какой-то причине мы получаем «InvalidOperationException: объект в настоящее время используется в другом месте».

во время нашего пользовательского OnPaint, ниже (на самом деле это почти построчная копия кода … там этого мало).

Мы регистрируемся в обработчике исключений ниже, чтобы определить, вызываем ли мы каким-то образом OnPaint из потока, отличного от пользовательского интерфейса … и это не срабатывает, но мы регистрируем эту ошибку (см. Трассировку стека ниже).

На машинах, где мы получаем эти ошибки, мы также видим страшный красный крест doom от других элементов управления (которые, по-видимому, не имеют try / catch вокруг своих OnPaint).

Вероятно, они связаны, но я не могу понять, что может быть причиной этой ошибки, если этот код вызывается только из потока пользовательского интерфейса.

Есть идеи?

Это трассировка стека:

Система.InvalidOperationException: объект в настоящее время используется в другом месте.
в системе.Рисование.Графика.Проверка состояния (статус Int32)
в системе.Рисование.Графика.Нарисуйте прямоугольник (Pen pen, Int32 x, Int32 y, Int32 width, Int32 height)
в системе.Windows.Формы.ControlPaint.DrawBorderSimple (графическая графика, границы прямоугольника, цвет цвета, стиль ButtonBorderStyle)
в системе.Windows.Формы.ControlPaint.DrawBorder(графическая графика, границы прямоугольника, цвет цвета, стиль ButtonBorderStyle)
в MyUserControl.OnPaint(PaintEventArgs e)

Это класс:

 public class MyUserControl : UserControl
{
    // Override this to set your custom border color
    protected Color mBorderColor = SystemColors.ControlDarkDark;

    public MyeUserControl()
        : base()
    {
        this.BorderStyle = BorderStyle.None;
        this.Padding = new Padding(1);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        try
        {
            ControlPaint.DrawBorder(e.Graphics, this.ClientRectangle, mBorderColor, ButtonBorderStyle.Solid);
        }
        catch (Exception ex)
        {
            // check if we're not on the UI thread, and if not, log it
            // log exception
        }
    }
}
  

Комментарии:

1. Подождите, он отключается.

2. Это не срабатывает. Регистрируемая ошибка — это просто ошибка из-за сбоя вызова DrawBorder. Есть отдельное сообщение журнала, в котором говорится: «OnPaint вызывается из потока, отличного от пользовательского интерфейса». Что мы определяем, проверяя InvokeRequired в основной форме приложения.

3. А затем GDI рвется, потому что перо используется одновременно в нескольких графических контекстах. Это не должно вас удивлять.

4. Извините, может быть, я недостаточно ясно выражаюсь. Существует отдельное сообщение об ошибке о том, что это вызывается в потоке, отличном от пользовательского интерфейса. Это сообщение журнала никогда не записывается. Похоже, что это никогда не вызывается из потока, отличного от пользовательского интерфейса. Одна из возможностей заключается в том, что он вызывается из потока, отличного от пользовательского интерфейса, но этот вызов никогда не завершается ошибкой, и поскольку проверка, не связанная с пользовательским интерфейсом, выполняется только в обработчике исключений, она никогда не вызывается. но тот же вызов, не относящийся к пользовательскому интерфейсу, вызывает вызов в потоке пользовательского интерфейса. Это возможность, и я ее изучаю… но вы могли бы подумать, что иногда сбой происходит из-за потока, отличного от пользовательского интерфейса.

Ответ №1:

Итак, я понял это некоторое время назад, но забыл указать ответ здесь. У всех клиентов с проблемой была одна общая черта — они установили плагин Adobe под названием FileOpen. Это позволяет пользователям читать зашифрованные PDF-файлы. Оказывается, что-то, что делал FileOpen (предположительно, для блокировки снимков экрана зашифрованных PDF-файлов или чего-то еще), мешало нашему приложению, вызывая исключения во время вызовов Windows GDI (которые вызываются из.Чистые методы OnPaint). При работе с FileOpen они внесли наше приложение в белый список, чтобы не блокировать вызовы GDI из нашего приложения.

Что сделало это еще более сложным для понимания, так это то, что блокировка происходит только после первого просмотра зашифрованного PDF-файла с помощью FileOpen… таким образом, вы можете установить его и не столкнуться с проблемой. Если вы остановите их службу Windows FileOpenBroker, это также устранит проблему (предположительно, служба выполняет блокировку).

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

Обновление: существует довольно простой обходной путь, который заключается в остановке службы FileOpen, которая называется FileOpenBroker . Вы должны быть в состоянии найти его в списке служб Windows и как процесс в диспетчере задач Windows. Как только процесс был остановлен, он останавливает все, что они делают, чтобы испортить GDI , и тогда вы сможете использовать свою программу до следующего открытия зашифрованного PDF.

Прошло некоторое время, поэтому я точно не помню, но, возможно, перезагрузка была необходима для снятия любых блокировок, которые они установили в GDI . Я помню, что я создал командный файл для запуска и остановки службы, чтобы вы могли использовать свою программу без полного отключения возможности использования FileOpen (который, я полагаю, установлен, потому что он используется на этом компьютере).).

Со мной только что связался кто-то другой, столкнувшийся с той же проблемой, поэтому кажется, что FileOpen не устранил основную проблему — они только наложили на нее пластырь, включив в белый список наше конкретное приложение … справедливое предупреждение.

Комментарии:

1. Вау, если бы этого ответа не существовало, я не уверен, сколько времени я бы потратил на получение no where. К вашему сведению, служба теперь, похоже, называется «FileOpenManager». Его остановка сразу устранила проблему (перезагрузка не требуется, только перезапуск приложения). Спасибо, что нашли время опубликовать этот ответ еще тогда.

Ответ №2:

Это сообщение в блоге объясняет сообщение об ошибке:

http://msmvps.com/blogs/peterritchie/archive/2008/01/28/quot-object-is-currently-in-use-elsewhere-quot-error.aspx

Я не могу сопоставить это с опубликованным вами кодом, хотя, есть ли какие-либо другие графические операции, выполняемые в этой форме?

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

Комментарии:

1. Ваша точка зрения о том, что поток, не связанный с пользовательским интерфейсом, завершается успешно, а поток пользовательского интерфейса завершается неудачно, является хорошей. Думаю, я бы просто ожидал, что поток, не относящийся к пользовательскому интерфейсу, будет терпеть неудачу хотя бы некоторое время, и мы этого вообще не видели… но, возможно, есть какой-то смягчающий фактор, который всегда приводит к сбою потока пользовательского интерфейса. Я переношу проверку потока, не относящегося к пользовательскому интерфейсу, в основную часть метода, это даст нам лучшую идею.