ObjectDisposedException после закрытия приложения по таймеру

Я работаю над сетевым приложением. Сначала я хотел, чтобы DataGridView обновлял свои данные каждую секунду. Моя реализация:

public partial class Form1 : Form
{
    BindingList<Wifi> Networks = new BindingList<Wifi>();
    System.Timers.Timer NetworksRefreshThread;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        NetshScanner netshScanner = new NetshScanner();
        NetworksRefreshThread = new System.Timers.Timer(1000);

        dataGridView1.DataSource = Networks;
        NetworksRefreshThread.Elapsed += delegate
        {         
            BindingList<Wifi> tmp = new BindingList<Wifi>(netshScanner.StartAndParseOutput());

                this.Invoke((MethodInvoker)delegate
                {
                    Networks.Clear();
                    foreach (Wifi net in tmp)
                    {
                        Networks.Add(net);
                    }

                });

        };
    }

После закрытия формы я получаю ObjectDisposedException внутри this.Invoke. Любой совет?


person ContentPenalty    schedule 08.08.2014    source источник
comment
Вы останавливаете таймер при закрытии формы?   -  person DavidG    schedule 08.08.2014
comment
Я добавил NetworksRefreshThread.Close() в событие Form1_FormClosing, но все равно. Я бы добавил, что это исключение не всегда появляется.   -  person ContentPenalty    schedule 08.08.2014
comment
Это поможет   -  person Sriram Sakthivel    schedule 08.08.2014


Ответы (1)


Что, вероятно, происходит, так это то, что таймер сработал и в настоящее время занят обновлением вашего DataGridView. Это происходит в отдельном потоке. Затем, когда вы закрываете форму, поток GUI начинает уничтожать ее объекты. После этого таймер завершает получение своих новых данных, но у него не осталось объекта для его размещения.

Чтобы решить это. Добавьте логическое значение в свой класс под названием «Обновление» или что-то подобное. Затем установите его значение при обновлении на true.

NetworksRefreshThread.Elapsed += delegate
{    
    Updating = true;     
    BindingList<Wifi> tmp = new BindingList<Wifi>(netshScanner.StartAndParseOutput());

        this.Invoke((MethodInvoker)delegate
        {
            Networks.Clear();
            foreach (Wifi net in tmp)
            {
                Networks.Add(net);
            }

        });
    Updating = false;
};

Теперь создайте новый метод, который вы привязываете к событию закрытия формы. В этом методе выполните Thread.Sleep() во время обновления таймера:

while (Updating) Thread.Sleep(100);
person Bart van der Drift    schedule 08.08.2014
comment
Но обновление выполняется в потоке графического интерфейса, поэтому я использовал this.Invoke((MethodInvoker)delegate). Внутри таймера я получаю данные в переменную tmp и передаю их потоку графического интерфейса для обновления. - person ContentPenalty; 08.08.2014
comment
Что ж, вы ПОПЫТАЕТЕСЬ заставить поток GUI сделать это... но поток GUI больше не существует после того, как вы закроете форму. - person Bart van der Drift; 08.08.2014
comment
Кажется, это проблема, но когда я изменил код с помощью логического значения Update, приложение зависло, когда возникла ситуация. - person ContentPenalty; 08.08.2014