Как определить момент завершения фонового потока?

Рейтинг: 1Ответов: 2Опубликовано: 24.02.2011

Создал Windows-приложение, состоящее из двух форм. На первой форме осуществляется запуск второй. Есть один нюанс. Перед запуском второй формы, происходит копирование файлов, которые потом будут задействованы во второй форме. Дело в том, что во время этого действия первая форма полностью зависает. Поэтому я решил использовать многопоточность. Для работы с файлами я создал новый фоновый поток. Мне необходимо определить время его завершения, чтобы запустить вторую форму, поскольку если я включу запуск второй формы в тот же поток, что и работа с файлами, то он выдаст исключение:

"Создание экземпляра элемента управления ActiveX "8856f961-340a-11d0-a96b-00c04fd705a2" невозможно: текущий поток не находится в однопоточном контейнере."

Что мне посоветуете?

Ответы

▲ 2

Для того чтобы проверить, работает поток или уже завершился, можно использовать свойство объекта Thread IsAlive. Для отслеживания этого момента я как-то сделал дополнительный фоновый поток (IsBackground = true), который в цикле с периодом 100 мс проверял, завершился ли интересующий нас поток, с помощью этого свойства. По завершении этого потока он выполнял определённые действия и сам завершался. Но тогда мне это нужно было для того, чтобы корректно завершить побочный поток при завершении главного; сам побочный поток делать фоновым было нельзя, так как он работал с файловой системой и требовал корректного завершения, а не молчаливого прерывания.

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

void Run(ThreadStart doSomething)
{
    if (doSomething == null)
        throw new ArgumentNullException("doSomething");

    if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
        doSomething();
    else
    {
        var th = new Thread(doSomething);

        th.SetApartmentState(ApartmentState.STA);
        th.Start();
        th.Join();
    }
}

То есть, если мы уже в однопоточном апартаменте, просто вызываем переданный через параметр делегат. Если нет, создаём новый поток в однопоточном апартаменте и ждём его завершения.

▲ 2

На потоках можно ждать. WaitForSingleObject().