Не может получить доступ к склонному объекту - Как зафиксировать?

В проекте VB.NET WinForms я получаю исключение

Не может получить доступ к избавленному объект

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

Cannot access a disposed object. Object name: 'dbiSchedule'.
  at System.Windows.Forms.Control.CreateHandle()
  at System.Windows.Forms.Control.get_Handle()
  at System.Windows.Forms.Control.PointToScreen(Point p)
  at Dbi.WinControl.Schedule.dbiSchedule.a(Boolean A_0)
  at Dbi.WinControl.Schedule.dbiSchedule.a(Object A_0, EventArgs A_1)
  at System.Windows.Forms.Timer.OnTick(EventArgs e)
  at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
  at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

dbiSchedule является управлением расписанием от Dbi-технологии. Существует таймер на форме, которая обновляет расписание на экране каждые несколько минут.

Какие-либо идеи, что вызывает исключение и как я мог бы пойти о фиксации его? или даже просто способность воссоздать его по требованию?


Hej! Спасибо за все ответы. Мы действительно останавливаем Таймер на событии FormClosing, и мы действительно проверяем свойство IsDisposed на компоненте расписания перед использованием его в событии Timer Tick, но это не помогает.

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

37
задан Jaymin 18 October 2019 в 08:40
поделиться

8 ответов

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

Мы действительно останавливаем Таймер на событии FormClosing, и мы действительно проверяем свойство IsDisposed на компоненте расписания перед использованием его в событии Timer Tick, но это не помогает.

Вызов GC.Collect прежде, чем проверить IsDisposed может помочь, но быть осторожным с этим. Прочитайте эту статью Rico Mariani" , Когда назвать GC.Collect () ".

19
ответ дан jfs 27 November 2019 в 04:59
поделиться

Похож на проблему поточной обработки.
Гипотеза : Возможно, у Вас есть основной поток и поток таймера, получающий доступ к этому управлению. Основной поток закрывается - называющий Управление. Расположите (), чтобы указать, что я сделан с этим Управлением, и я не выполню больше вызовов к этому. Однако поток таймера все еще активен - контекстное переключение к тому потоку, где это может назвать методы на том же управлении. Теперь управление говорит, что я Расположен (уже брошенный мои ресурсы), и я не буду больше работать. Исключение ObjectDisposed.

, Как решить это : В потоке таймера, перед тем, чтобы называть методы/свойства на управлении, делают проверку с

if ControlObject.IsDisposed then return; // or do whatever - but don't call control methods

ИЛИ останавливают поток таймера ПРЕЖДЕ, ЧЕМ расположить объект.

10
ответ дан Jaymin 27 November 2019 в 04:59
поделиться

мы действительно проверяем свойство IsDisposed на компоненте расписания перед использованием его в событии Timer Tick, но это не помогает.

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

Вы, явно вызов Располагает на их управлении?

2
ответ дан Will Dean 27 November 2019 в 04:59
поделиться

Остановка таймера не означает, что это не назовут снова, в зависимости от того, когда Вы остановите таймер, timer_tick может все еще быть поставлен в очередь на цикле сообщения для формы. То, что произойдет, - то, что Вы получите еще одну галочку, которую Вы не можете ожидать. То, что можно сделать, находится в timer_tick, проверьте свойство Enabled таймера прежде, чем выполнить метод Timer_Tick.

2
ответ дан Garo Yeriazarian 27 November 2019 в 04:59
поделиться

Вы уверенный таймер не переживает 'dbiSchedule' так или иначе и стреляет после того, как 'dbiSchedule' был избавлен?

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

1
ответ дан imaginaryboy 27 November 2019 в 04:59
поделиться

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

1
ответ дан samjudson 27 November 2019 в 04:59
поделиться

Если это происходит, эпизодически тогда мое предположение - то, что это имеет некоторое отношение к таймеру.

я предполагаю (и это - только предположение, так как у меня нет доступа к Вашему коду), который запускает таймер, в то время как форма закрывается. Объект dbiSchedule был расположен, но таймеру так или иначе все еще удается попытаться назвать его. Это не было должно происходить, потому что, если таймер имеет ссылку на объект расписания тогда, сборщик "мусора" должен видеть это и не избавиться от него.

Это приводит меня спрашивать: Вы - вызов, Располагают () на объекте расписания вручную? Если так, Вы делаете это перед избавлением от таймера? Убедитесь, что Вы выпускаете все ссылки на объект расписания прежде, чем Расположить его (т.е. избавляетесь от таймера заранее).

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

Hope это помогает.

1
ответ дан Jaymin 27 November 2019 в 04:59
поделиться

Смотря на ошибочное отслеживание стека, кажется, что Ваш таймер все еще активен. Попытайтесь отменить таймер после закрытия формы ( т.е. в OnClose формы () метод). Это похоже на самое чистое решение.

0
ответ дан On Freund 27 November 2019 в 04:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: