0x01AA Ответов: 1

Неверная интерпретация c# weakreference при использовании его для форм?


Уважаемые эксперты
Похоже, я не понимаю, в чем дело. WeakReference Моя цель состоит в том, чтобы позволить "наблюдать" время жизни формы с помощью WeakReference.

В моей основной форме я создаю Формтест, используя слабую ссылку:
    public partial class FormMain : Form
    {
        private WeakReference weakRefFormTest= null;

        private void buttonNewForm_Click(object sender, EventArgs e)
        {
            if (weakRefFormTest == null)
            {
		// Create WeakReference and the form
                weakRefFormTest = new WeakReference(new FormTest());
                ((Form)weakRefFormTest.Target).Show();
            }
            else
            {
		// Check form alive  *1)
                Form formTest = (Form)weakRefFormTest.Target;
                if (formTest != null)
                {
                    formTest.Visible = !formTest.Visible;
                }
            }
        }
	...
	......
    }

* 1) здесь я ожидаю, что (Form)weakRefFormTest.Target будет иметь значение null после закрытия тестовой формы. Но это не так, это даст мне всегда "действительную" форму. Также weakRefFormTest.IsAlive возвращает true после закрытия formTest. И используя затем форму в коде выбрасывает System.ObjectDisposedException

Можете ли вы указать мне на то, чего я не понимаю, где я ошибаюсь?


Н.б.: я знаю, что мог бы подписаться на Form. Closed-Event, но мне не нравится такой подход.

Заранее большое вам спасибо.

Что я уже пробовал:

См. фрагмент кода в вопросе.

Hermann Jung

Слабая связь.Target будет равен null, когда GarbageCollector соберет форму. Form. Close () не вызывает GC.Collect () - и вы не должны делать это в своем коде (см. документацию GarbageCollector). Вероятно,вам следует провести еще одну проверку формы.IsDisposed.

0x01AA

Спасибо за ваш комментарий. Кажется, мне нужно погрузить деппера во все это.

0x01AA

Да конечно вы правы, if ((formTest != null) && !formtest.IsDisposed)) это приемлемый способ. Я думал о чем-то подобном, но только искал недвижимость Disposed Я предлагаю опубликовать его как решение :-)

1 Ответов

Рейтинг:
8

OriginalGriff

Посмотрите на документацию: Слабая связь.Целевое Свойство (Система)[^]
И в нем говорится, что:

Property Value
Type: System.Object
null if the object referenced by the current WeakReference object has been garbage collected; otherwise, a reference to the object referenced by the current WeakReference object.
Просто потому, что он закрыт, не означает, что он был освобожден сборщиком мусора - помните, что сборщик мусора всегда включается в действие только тогда, когда заканчивается память, или Dispose вызывается для объекта Закрытие формы не делает ни того, ни другого, иначе вы не сможете получить доступ к содержимому формы, как только пользователь закончит ее заполнять и нажмет " ОК":
frmLogin f = new frmLogin();
if (f.ShowDialog() == DialogResult.OK)
   {
   string username = f.UserName;
   ...
   }
Если вы хотите знать, когда форма закрыта, вам нужно использовать событие, а не слабую ссылку.

[edit]:doh: мне нужно больше кофеина...[/редактировать]


0x01AA

Большое вам спасибо за Ваш быстрый ответ +5. Вы пишете "... или Dispose вызывается на объекте. Закрытие формы не делает ни того, ни другого ... "но если я прочитаю документацию MSDN, то найду:" когда форма закрыта, все ресурсы, созданные внутри объекта, закрываются, а форма выбывает"И именно это привело меня к мысли,что WeakRef подходит.

OriginalGriff

Простите - мне следовало объяснить более ясно - мою ошибку.
Dispose вызывается для формы, когда она закрыта, и отвечает за завершение цикла сообщений, освобождение дескриптора Windows и такие вещи, как очистка ресурсов.
Но Dispose не освобождает память кучи для класса - это может сделать только сборщик мусора - и он не вызывает сборщик мусора, чтобы начать освобождение. Он просто помечает экземпляр как "утилизированный", чтобы GC не пришлось вызывать его снова, когда он решит, что память экземпляра может быть освобождена.
Если Dispose вызвал освобождение, то в любом месте, где использовался блок * using*, он будет непредсказуемо медленным:
using (SqlConnection con = new SqlConnection(strConnect))
{
против.Открыть();
используя (команда sqlcommand cmd и = новая команда sqlcommand("выберите ID, описание из mytable", кон))
{
использование (SqlDataReader reader = cmd.Метода executereader())
{
в то время как (читатель. читать())
{
int id = (int) reader ["Id"];
string desc = (string) reader ["описание"];
Приставка.WriteLine ("ID: {0}\n {1}", id, desc);
}
}
}
}
Активировал бы ГК три раза! :смеяться:
GC вызывается в действие только тогда, когда запрос памяти не может быть выполнен или он явно вызывается через GC.Собирать.

0x01AA

Отлично, еще раз спасибо вам за это! Извините не могу проголосовать больше 5 и принять его только один раз :-)

0x01AA

И форма, я думаю, утилизирована, потому что исключение составляет System.ObjectDisposedException- верно или опять неверное толкование с моей стороны?

OriginalGriff

Я думаю, что он пытается использовать weakreference, чтобы сказать ему, когда форма закрыта - и это означает событие FormClosed.