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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Форма в отдельном потоке 
V
    Опции темы
Enteropoly
Дата 2.8.2009, 23:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Привет!

Вопрос достаточно простой, задаю по причине того, что сегодня необычайно лень думать =)) 

Надобно мне, чтобы форма работала целиком в отдельном потоке. Есть, к примеру, GUI Thread, в котором месится главная форма, вот мне хочется запустить другую форму в другом потоке =)

Делаю так:
Код

private Layer3 _layer3 = null;
private Thread _thread3 = null;

//в конструкторе
this._thread3 = new Thread(new ThreadStart(this.StartLayer3));
this._thread3.Start();

private void StartLayer3()
        {
            this._layer3 = new Layer3(this);
            this._layer3.Show();
        }


Не работает =) Подозреваю, что форма создаётся, но поток тут же завершается. Есть мнение, что нужно применить что-то типа while (true), чтобы поток не завершался, но как это сделать в случае с формой? =)

Заранее благодарю за внимание  smile 

ЗЫ. Есть одно условие. С главной формы обязательно нужно иметь возможность обращаться к этой форме в другом потоке.

Это сообщение отредактировал(а) Enteropoly - 2.8.2009, 23:10
PM MAIL   Вверх
Экскалупатор
Дата 2.8.2009, 23:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

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



Enteropoly, если не секрет, то для чего такие сложности?
PM MAIL ICQ   Вверх
Enteropoly
Дата 2.8.2009, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Конечно не секрет, всё давно уже описано =)

http://forum.vingrad.ru/forum/topic-266901.html

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

ЗЫ. А в целом, для производительности. Рисовать на двух формах в двух потоках, думается мне, быстрее, чем на двух формах в одном потоке =)

Это сообщение отредактировал(а) Enteropoly - 3.8.2009, 00:01
PM MAIL   Вверх
Экскалупатор
Дата 3.8.2009, 00:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

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



Enteropoly, далеко не всегда, если это будет работать в системе где будет не один процессор, то да, выигрыш будет, но если проц один, то и обрабатывать он будет все потоку по очереди, а не одновременно, плюс затраты на переключение между потоками, все это требует доп ресурсов и как результат будет работать медленнее чем в одном потоке.
PM MAIL ICQ   Вверх
Enteropoly
Дата 3.8.2009, 00:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Ну, в принципе, планируется сделать поддержку и одно-, и многоядерных процессоров =)

Итак, что тут я подумал-то... Есть ведь такая штука, которая называется Pipelining (кто знаком с процессорной архитектурой RISC, поймёт сразу). Заключается она в том, что:
- есть поток А и поток Б
- поток А служит приёмником информации и инициатором действий
- поток Б отвечает за исполнение этих самых действий.

Проще говоря, есть форма А в потоке А. Клик на форму А (приём информации) инициирует некое действие (например, перерисовать форму). У формы Б в потоке Б есть буфер, куда помещаются команды от формы А и постоянно выполняющийся метод, который и служит для того, чтобы исполнять команды.

Ещё проще говоря, поток А помещает в буфер потока Б какую-нибудь команду. Поток Б постоянно смотрит в свой буфер и если видит, что надо что-то делать, делает это в своём потоке =) Потокобезопасность на высоте, все довольны и счастливы  smile 

Теоретически (!) должно сработать =) Но проверю попозже. Такие штуки без зелья не делаются =))  smile 

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

Это сообщение отредактировал(а) Enteropoly - 3.8.2009, 00:52
PM MAIL   Вверх
Enteropoly
Дата 3.8.2009, 01:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Переписал пример, может кому-нибудь потом пригодится =)  smile 

Пайплайн
Код

    //команда конвейера
    //
    public struct PipelineCommand
    {
        public string Name;
        public object[] Params;
    }

    //конвейер обработки информации
    //
    public class Pipeline
    {
        private Queue<PipelineCommand> _pcQueue;
        private PipelineCommand _pcCurrent;
        private bool _isAlive = true;
        private bool _isPaused = false;

        public Pipeline()
        {
            this._pcQueue = new Queue<PipelineCommand>() ;
        }
        public Pipeline(int BufferSize)
        {
            this._pcQueue = new Queue<PipelineCommand>(BufferSize);
        }

        public void Start(int Performance)
        {
            while (this._isAlive)
            {
                Thread.Sleep(Performance);

                if (!this._isPaused)
                {
                    if (this._pcQueue.Count != 0)
                    {
                        this._pcCurrent = this._pcQueue.Dequeue();

                        switch (this._pcCurrent.Name)
                        {
                            case "ShowMSGBox":
                                MessageBox.Show((string)this._pcCurrent.Params[0]);
                                break;
                        }
                    }
                }
            }
        }

        public void Enqueue(PipelineCommand PC)
        {
            this._pcQueue.Enqueue(PC);
        }

        public void Pause(bool Set)
        {
            this._isPaused = Set;
        }

        public void Stop()
        {
            this._isAlive = false;
        }

        public PipelineCommand ShowNext()
        {
            if (this._pcQueue.Count != 0)
            {
                return this._pcQueue.Peek();
            }
            else
            {
                return new PipelineCommand { Name = "", Params = null };
            }
        }
    }


Этот код мы помещаем в форму, которая будет работать в потоке Б (исполнять команды)
Код

private Pipeline _pipe = new Pipeline();

        public Form(out Pipeline Pipe)
        {            
            Pipe = this._pipe;

            //...

            this._pipe.Start(100);
        }

 ВНИМАНИЕ!  Из-за того, что конвейер запускается прямо из конструктора, экземпляр формы НЕ СОЗДАСТСЯ и вы не сможете к нему обращаться! Но это и не нужно, поскольку вы делаете финт ушами, предоставляя управляющему классу сам конвейер, а с помощью конвейерных команд можно управлять этой же самой формой как угодно.

А так мы создаём форму Б из формы А (раздающей команды)
Код

private Pipeline _pipe = null;
private Thread _thread = null;

public Form()
        {
            Thread.CurrentThread.Name = "MainThread";

            this._thread = new Thread(new ThreadStart(this.StartAnotherForm));            
            this._thread.Start();

            //...
         }

private void StartAnotherForm()
        {            
           Form _f = new Form(out this._pipe);            
        }


Послать команду из формы А в форму Б очень просто
Код

this._pipe.Enqueue(new PipelineCommand
            {
                Name = "ShowMSGBox",
                Params = new object[] { Thread.CurrentThread.Name }
            });


Всё работает как часы =) Вспомогательные формы можно ставить на паузу (Pipeline.Pause(true)), а отключать, вызвав метод Pipeline.Stop()

Это не отражено в примере, но, как можно было бы догадаться, в конструктор Pipeline нужно так же передавать либо Control, либо, интерфейс, чтобы можно было к чему-либо обращаться.

Это сообщение отредактировал(а) Enteropoly - 3.8.2009, 14:02
PM MAIL   Вверх
Enteropoly
Дата 3.8.2009, 01:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Да, кому интересно, эту идею (не реализацию) я нашёл в бесплатном документике Andrew D. Birrell, An Introduction to Programming with C# Threads, который можно скачать тут. Много интересного про потоки (но нужно знать английский).

Апдейт. Поменял примерчик в посте выше. Теперь тему можно благополучно забыть и оставить для потомков  smile 

ЗЫ. Как вы понимаете, подобную штуку можно использовать для любого контрола, который необходимо запустить в другом потоке.

Это сообщение отредактировал(а) Enteropoly - 3.8.2009, 12:41
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

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


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

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


 




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


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

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