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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Потоки, Почему не работает такой приемр 
:(
    Опции темы
savage
Дата 20.10.2007, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Всем привет. Только не отправляйте сразу в поиск - там уже был.
Встала проблема при организации отдельного потока в приложении Windows Forms. Я просмотрел все что на форуме сть, все пользуются Invoke и BeginInvoke, сам с потоками только в консольных приложениях работал через Thread, и поэтому особых проблем раньше не было.

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

Код

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void setToText()
        {
            while (true)
            {
                if (this.textBox1.InvokeRequired == false) this.textBox1.Text = DateTime.Now.ToString("HH:mm:ss");
                else
                {
                    setToTextDelegate stt = new setToTextDelegate(setToText);
                    this.BeginInvoke(stt);
                }
                Thread.Sleep(1000);
            }
        }

        delegate void setToTextDelegate();

        private void button1_Click(object sender, EventArgs e)
        {
            setToTextDelegate stt = new setToTextDelegate(setToText);
            stt.BeginInvoke(null, null);
        }
    }
}



PM MAIL   Вверх
archeg
Дата 20.10.2007, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 612
Регистрация: 6.1.2007
Где: Киев

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



Код

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void setToText()
        {
                if (this.textBox1.InvokeRequired == false) {this.textBox1.Text = DateTime.Now.ToString("HH:mm:ss");return}

            while (true)
            {
                
                    setToTextDelegate stt = new setToTextDelegate(setToText);
                    this.BeginInvoke(stt);
                
                Thread.Sleep(1000);
            }
        }

        delegate void setToTextDelegate();

        private void button1_Click(object sender, EventArgs e)
        {
            setToTextDelegate stt = new setToTextDelegate(setToText);
            stt.BeginInvoke(null, null);
        }
    }
}


У тя там какая-то странная рекурсивность...
П.С. Что за гугл к топику прилип???? Он меня бесит  smile  Уберите!!  smile  smile 

Это сообщение отредактировал(а) archeg - 20.10.2007, 14:42


--------------------
ИМХО задница есть универсальный интерфейс. Ибо через задницу можно сделать абсолютно ВСЕ (bash.org.ru)

Дядька всегда можно спросить в аське, если не задалбывать - не откажет smile
И вообще, на самом деле я студент, и ненавижу обращение на "Вы") Тут все свои  ;)
PM MAIL ICQ Jabber   Вверх
tol05
Дата 20.10.2007, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

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



Да я вообще не пойму замысла savage..

Что делает этот пример? Ну нажали кнопку, и что? Все происходит в одном потоке, второго нет. Так зачем Invoke? Это раз.

Во-вторых, допустим нажали кнопку и делегат сработал. Зашли в setToText()
BeginInvoke породил новый поток и текстбокс нуждается в Invoke. Вызвали. И дальше - все, тушите свет. 
Код

 while (true)
это жесть!  smile 
конечно бесконечная рекурсия с тем же делегатом, который вызывает BeginInvoke на самого себя... Короче - непонятно что хотел автор.

Цитата(savage @  20.10.2007,  14:24 Найти цитируемый пост)
так ведь вроде все делают

никто так не делает. Ты сделал делегат для обновления текстбокса? Ну так и обнови его. Зачем снова BeginInvoke вызывать?

Цитата(archeg @  20.10.2007,  14:37 Найти цитируемый пост)
П.С. Что за гугл к топику прилип???? Он меня бесит
Это новый участник форума! Ты ответь ему, чтоб не постился больше. Или модераторов попроси забанить за оффтоп его!!
smile 

мда. Похоже скоро винград станет гаджетом гугл. Все к этому идет  




--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
savage
Дата 20.10.2007, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



archeg, спасибо!
Цитата

Что делает этот пример? Ну нажали кнопку, и что? Все происходит в одном потоке, второго нет. Так зачем Invoke? Это раз.

tol05, я понимаю что это выглядит как сборная солянка  smile но это только из-за того что я еще толком не могу въехать как(к чему и почему) использовать invoke.
Пример такой выбрал потому что для меня то по сути не важно что там делается обновляется текстовое значение текст бокса или делаются какие то вычисления. Решил просто попробовать сделать что то элементарное, по типу таймера, для практики работы взаимодействия потоков и контролов формы.
Я под консоль делал на Thread`ах, там небыло таких проблем, проще как то было. А сейчас тонкостей всяких с формами еще не знаю. Вот и копаюсь.
Цитата

 while (true)

А есть альтернативный способ? Только не таймер.

Ну и раз уж так. Не могли б вы объяснить, как же тогда грамотно организовать работу дополнительного потока, чтоб он мог изменять контролы на форме? Хотяб даже на моем простом примере.
PM MAIL   Вверх
archeg
Дата 20.10.2007, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 612
Регистрация: 6.1.2007
Где: Киев

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



Цитата(tol05 @  20.10.2007,  15:09 Найти цитируемый пост)
Что делает этот пример? Ну нажали кнопку, и что? Все происходит в одном потоке, второго нет. Так зачем Invoke? Это раз.

Не въехал, как нет другого потока? Это ж АРМ smile 

Цитата(savage @  20.10.2007,  16:17 Найти цитируемый пост)
А есть альтернативный способ? Только не таймер.

Я не понимаю, почему люди так не любят таймеры? )

Да и вообще я против вызовов самого себя(я про метод setToText  smile )  в таком примере - только путаешься  smile 
Цитата(tol05)

Код

 while (true)

 это жесть!   

Я так понимаю эт просто пример) вряд ли кто-то так в коде будет писать....

Цитата(tol05)

мда. Похоже скоро винград станет гаджетом гугл. Все к этому идет  

эххх (

Это сообщение отредактировал(а) archeg - 20.10.2007, 18:20


--------------------
ИМХО задница есть универсальный интерфейс. Ибо через задницу можно сделать абсолютно ВСЕ (bash.org.ru)

Дядька всегда можно спросить в аське, если не задалбывать - не откажет smile
И вообще, на самом деле я студент, и ненавижу обращение на "Вы") Тут все свои  ;)
PM MAIL ICQ Jabber   Вверх
tol05
Дата 20.10.2007, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

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



savage, ок. Когда-то несколько топиков было на эту тему, но пока их найдешь... Проще еще раз написать... Итак:

Немного теории:
   Вин-формс контрол позволяет с собой работать только в том потоке, где он был создан. Т.е. в основном потоке программы (помеченном STAThread). Если нужно из другого потока обратиться к контролу - используется технология Invoke (о том, какие потоки часто требуют этого - ниже напишу). Если обращение к контролу идет из того же потока - Invoke не требуется.
   Как работает Invoke? Просто. Каждый поток имеет очередь сообщений. Контрол, к примеру, создан в потоке А. Вызвовом Invoke() из потока B мы посылаем сообщение потоку А (типа "а ну-ка вызови нам метод TextBox.Refresh()" ). 
   Посланное сообщение попадает в очерь потока А, а мы продолжаем работу в потоке B дальше (если вызывали BeginInvoke) или сидим в своем потоке B и ждем результатов (если вызывали Invoke). 
   Поток А отработал свою текущую задачу (через полчаса smile ) и полез к себе в очередь сообщений смотреть, нет ли новых задач. Увидел наше сообщение и начал отрабатывать его. Поэтому вызов Invoke не всегда приводит к немедленному действию, можно достаточно долго ждать его результатов.
   Контрол имеет свойство Control.InvokeRequired - оно говорит, нужно ли использовать Invoke или нет (т.е. находишься ли ты в основном потоке или ты сейчас находишься во внешнем по отношению к контролу потоке). Это свойство - для удобства. Я им никогда не пользуюсь потому что всегда сам знаю "Required" ли контрол Invoke или нет smile Просто самой архитектурой программы это обеспечиваю.
   Какие могут быть "другие потоки" - это рабочие потоки Thread, потоки пула потоков, потоки АРМ (Asynchronous Programming Model - те же потоки пула, на самом деле), потоки ввода/вывода. Ну и все, по-моему (BackGroungWorker я в расчет не беру - не люблю его... К нему, ИМХО, привыкнешь - вообще с потоками работать разучишься smile )

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

public partial class Form1 : Form
    {
        delegate void setToTextDelegate();
                setToTextDelegate stt = new setToTextDelegate(setToText);

        public Form1()
        {
            InitializeComponent();
            Thread thread = new Thread(Start);
            thread.Start();
        }

        private void Start()
        {
            stt.Invoke();
        }

        private void setToText()
        {
            if(this.textBox1.InvokeRequired == false)
            {
                this.textBox1.Text = DateTime.Now.ToString("HH:mm:ss");
            }
            else
            {
                this.BeginInvoke(stt);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //асинхронный вызов
            stt.BeginInvoke(null, null);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //синхронный вызов
            stt.Invoke();
        }
    }


Цитата(archeg @  20.10.2007,  18:14 Найти цитируемый пост)
Не въехал, как нет другого потока? Это ж АРМ 

Я имел в виду, что в программе не используются никакие другие потоки, кроме основного. Ну а то, что АРМ автор сам создает через BeginInvoke (хотя мог бы Invoke - и не было бы тогда АРМ  smile ) - это ж его выбор... ситуация этого не требовала...
Я это имел в виду.

Это сообщение отредактировал(а) tol05 - 20.10.2007, 18:49


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
savage
Дата 20.10.2007, 19:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



tol05, благодарю за развернутый ответ! многое прояснилось! Спасибо большое  smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

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


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

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




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


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

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