Модераторы: gambit, Partizan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Доступ из одного потока к форме, Небольшое уточнение известного вопроса 
:(
    Опции темы
Qwe2
Дата 17.9.2013, 22:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 36
Регистрация: 23.3.2008

Репутация: нет
Всего: нет



Вопрос про поток и UI не новый, хочу уточнить несколько несложных моментов:

1) Я во втором потоке меняю значение контрола, напрмер так:
Код

void ThreadFunction()
{
    for (int i = 0; i < 10; i++)
        richTextBox1.Invoke(PrintDelegateFunc, new object[] { i.ToString() });
}

Если мне надо менять несколько контролов в другом потоке, то для каждого нужен свой делагат с методом? И как быть с самой формой: можно ли менять ее параметры (размер, положение, цвет фона) во втором потоке?

2) Как из второго потока динамически создать контрол (или несколько) на форме?

3) Могу ли я по окончанию асинхронного процесса, в методе CallBack, менять значения контролов на форме (вернее как)? И саму форму можно ли менять и создавать динамически другие контролы?
Код

delegate void Copy();
<...>

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    Copy cpy = new Copy(CopyMy);
    IAsyncResult res = cpy.BeginInvoke(new AsyncCallback(CallBack), null);
}

void CallBack(IAsyncResult r)
{
    // Что можно делать с формой и контролами здесь и как?
}

PM MAIL   Вверх
jsharp36
Дата 18.9.2013, 06:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.10.2011

Репутация: 1
Всего: 1



Вы видимо не совсем понимаете, что есть главный поток в виндовс-приложении. Такое приложение в своей основе имеет бесконечный цикл с опрашиванием очереди сообщений. Нет сообщений - ничего не делает. Есть - начинает обрабатывать. Нажатие мышки или перетягивание формы, нажатие кнопки. Этот цикл скрыт. Программисты же пишут уже обработчики, которые вызываются в этом цикле. Именно поэтому, если обработчик выполняется долго, то приложение "не отвечает", если по нему тыкать мышкой. Конечно, не отвечает - потому как цикл остановился на одной итерации и отрабатывает обработчик и не выбирает новые сообщения от виндовс.
Чтобы корректно отрисовывалось и отрабатывало - все операции над формами и контролами надо производить в главном потоке. Что такое Invoke? Грубо можно представить, что тот главный цикл все время то обрабатывает сообщения, то засыпает, ничего не делая. Т.е. есть "дыры", когда он может приняться за вашу работу. Invoke для любого контрола или формы позволяет "вклинить" работу кода в главный поток.
Исходя из этого по вопросам:
1)Kак хотите. Invoke для текстбокса - это захват главного потока. А там хоть большой кусок кода пишите, который формы меняет, другие контролы.
2) Пишете метод, который создает контролы и цепляет их на форму, но только вызываете метод через Invoke для формы - тоже, чтобы это произошло в главном гуи-потоке, чтобы корректно отработало, отрисовалось.
3) Всё, о чем надо заботиться, это чтобы работа с GUI была в главном потоке. Просто задавайте себе вопрос, в каком потоке работает метод. CallBack() в отличии от OnLoad работает не в главном потоке. Поэтому оттуда надо снова Invoke какого-то контрола или формы. Просто можно this.Invoke - т.к. класс формы.

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
Qwe2
Дата 18.9.2013, 08:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 36
Регистрация: 23.3.2008

Репутация: нет
Всего: нет



Спасибо, многое прояснилось! На основании Вашего ответа получилось следующее (см. код), вопрос: почему визуально форма закрывается немного раньше, чем прогресс-бар доходит до максимума? Мне надо по завершении потока либо закрыть форму, либо что-то еще сделать с формой. Кстати, из вторичного потока можно закрывать форму или надо опять Invoke делать?

Код

namespace PBarAndProc
{
    public partial class Form1 : Form
    {
        delegate void Copy();
        delegate void SetChangeForm(string s);
        
        public Form1()
        {
            InitializeComponent();            
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            Copy CpyDelegate = new Copy(CopyFiles);
            IAsyncResult res = CpyDelegate.BeginInvoke(new AsyncCallback(CopyFiles_CallBack), null);
        }

        void CopyFiles()
        {
            for (int i = 0; i < 100; i++)
            {
                this.Invoke(new SetChangeForm(SetChangeFormFunc), new object[] { (i + 1).ToString() });
                Thread.Sleep(50);
            }
        }

        void SetChangeFormFunc(string s)
        {
            label1.Text = s;
            progressBar1.Value++;
        }

        void CopyFiles_CallBack(IAsyncResult r)
        {
            this.Close();
            // или добавить контрол и прочее
        }
    }
}

PM MAIL   Вверх
jsharp36
Дата 18.9.2013, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.10.2011

Репутация: 1
Всего: 1



Всё нормально с прогресс-баром, я проверил. Он визуально немного отстает. Если уберете закрывание формы и поиграетесь цифрами в цикле, например, до 90 - то он остановится на 90. Если сотня - то он доходит до конца. Но немного опаздывает его прорисовка. Не знаю, зачем так сделано. Возможно, слишком быстрый цикл. Это не существенно, если вы будете прогресс баром отображать какие-то реальные процессы, за которыми можно будет следить.

Бегло погуглил, проблема известная. Я бы не парился. Если Вы собираетесь профессионально заниматься программированием под WinForms, то никто не пользуется их родными контролами. DevExpress почти без вариантов.

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
jsharp36
Дата 18.9.2013, 10:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.10.2011

Репутация: 1
Всего: 1



Да, и нормальной практикой есть, даже не следить, из какого потока запускается. У контролов есть хитрое свойство. Можете понаписывать такие обертки:

Код

void SetLabelText(string s)
{
    if (label1.InvokeRequired)
    {
        label1.Invoke(new Action(() => label1.Text = s));
    }
    else
    {
        label1.Text = s;
    }       
}


И вызывать из любого потока не задумываясь

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
jonie
Дата 19.9.2013, 09:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 5
Всего: 118



Цитата(Qwe2 @  17.9.2013,  23:26 Найти цитируемый пост)

Если мне надо менять несколько контролов в другом потоке, то для каждого нужен свой делагат с методом? И как быть с самой формой: можно ли менять ее параметры (размер, положение, цвет фона) во втором потоке?

Для того, чтобы сделать маршалинг в поток UI возможно использовать не только Control.Invoke (или BeginInvoke) вызовы.
Если у вас есть длительная операция, которая требует "уведомления" UI , то можно захватить в свой рабочий поток контекст синнхронизации (используя SynchronizationContext.Current при создании потока). Далее, для маршалинга использовать его методы (в зависимости от нужного поведения - Post или Send (Send блокирует поток до выполнения смаршаленного делегата). Более того: методы Control.Invoke тоже самое и делают.


Цитата(Qwe2 @  17.9.2013,  23:26 Найти цитируемый пост)

2) Как из второго потока динамически создать контрол (или несколько) на форме?

аналогично п1.


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Разработка Windows Forms | Следующая тема »


 




[ Время генерации скрипта: 0.0736 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.