Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > [WPF] Создать контрол в отдельном треде


Автор: Kefir 20.9.2007, 16:49
Итак, проблема такова:
1. Есть UserControl (назовём его MyUserControl), который показывает информацию (не суть какую).
2. Для присвоения информации у контрола есть проперти:
Код

public Info Info
{
    get { return this._Info; }
    set
    {
        this._Info = value;
        // дальше идёт загрузка картинок, панорама, интерактивная карта и тому подобное, что занимает достаточно немало времени
    }
}

Вывод - надо создавать этот контрол в отдельном треде, а в главном треде показывать табличку "Подождите".
Итак.
Код

        // Это метод для вызова из главной программы
        private void LoadInfo(Info info)
        {
            // Это мы говорим, что надо начать показывать картинку загрузки
            this._Host.LoadScreenStart("Please wait. Loading information about " + department.Name + "...");
            // Создаём тред
            Thread t = new Thread(this.ThreadNewMyUserControl);
            // Как показала практика, нужен СТА тред для создания контролов (иначе будет эксепшн)
            t.SetApartmentState(ApartmentState.STA);
            // запускаем тред
            t.Start(info);
        }

        // Это метод, который будет в треде
        private void ThreadNewMyUserControl(object info)
        {
            // Создаём контрол
            MyUserControl uc = new MyUserControl();
            // Присваеваем проперти нужное значение
            uc.Info = (Info)info;
            // Говорим что треда закончилась.
            // this._SyncContext - это поле класса типа SynchronizationContext.
            // получается в конструкторе как = SynchronizationContext.Current
            this._SyncContext.Post(this.FinishLoading, uc);
        }

        // Это метод, который будет вызван через this._SyncContext из метода ThreadNewMyUserControl при завершении работы
        private void FinishLoading(object result)
        {
            // Вот это и есть проблемное место. Внутри функции AddTab созданный контрол добавляется на главную форму
            // и выводит эксепшн "The calling thread cannot access this object because a different thread owns it."
            this.Host.AddTab("blah-blah", (result as MyUserControl).Info.Name, (MyUserControl)result);
            // Говорим, что надо убрать табличку загрузки
            this._Host.LoadScreenStop();
        }

собственно говоря вот и проблема (на строке 32 кода, строки 30-31 - описание проблемы). созданный в другом треде контрол недоступен из главного треда. что делать?

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

В общем, помогите, люди добрые.

Автор: Kefir 21.9.2007, 15:25
небольшой апдейт.
1. вариант создать с UI тереде и присвоить проперти из другого не проходит, ибо делается это через Invoke, который блокирует UI тред. Увидел слово async в описании BeginInvoke и всё равно сразу сник, ибо это совсем не то что надо. Вывод - это невозможно, потому что  объект всё равно принадлежит UI треду, а значит и присвоение проперти будет проходит в UI треде.
2. вообще смысл всей этой проблемы в том, что я хочу показать "Подождите" пока грузится контрол. так вот я смотрел на это очень однобоко. решение очень простое - создать ещё одно окно и показывать его примерно так:
Код

PopupWindow pw = new PopupWindow();
pw.Show();

// грузим нужные контролы

pw.Hide();

Вот и всё. До сих пор не понимаю как это я сразу не догадался.

Вывод:
1) создать контрол в отдельном треде невозможно...
2) ...и ненужно, ибо вышеописанный способ решает эту проблему намного проще.
Вопрос помечаю решённым.

Добавлено через 1 минуту и 16 секунд
ЗЫ А вообще мне нравится как я тут создаю темы и сам себе потом пишу ответы в последнее время (по крайней мере относительно WPF и подобного).

Автор: thomas 21.9.2007, 17:07
Kefir, 
Так с WPF ни кто практически не работает.

А этот контрол, я так понимаю, ты хотел на своем сайте использовать? 

Автор: Kefir 21.9.2007, 18:46
я же не в упрёк форуму сказал. просто так, к слову  smile 
а под веб я не нишу. виндовское приложение у меня.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)