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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Невыполнение Idle при работе со списком. 
:(
    Опции темы
Mal Hack
Дата 4.1.2007, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



Код
// OnIdle EventHandler
        private void FncIdle(object sender, EventArgs e)
        {
            if (this.idle == false)
            { return; }

            if (cb.Text == "Не найдено сервисов." || cb.Text == "Выберите из списка.")
            {
                lblServiceNameInfo.Text = "";
                lblServicePathInfo.Text = "";
                lblServiceStatusInfo.Text = "";

                return;
            }

            LWS_UpdateInfo();
        }

// ComboBox
        private void cb_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cb.Text == "Не найдено сервисов." || cb.Text == "Выберите из списка.")
            {
                lblServiceNameInfo.Text = "";
                lblServicePathInfo.Text = "";
                lblServiceStatusInfo.Text = "";

                return;
            }

            LWS_UpdateInfo();
        }

При выборе элемента списка из комбобокса, вызывается  LWS_UpdateInfo();. Она же вызывается, в OnIdle.
Не знаю как, но когда я открываю список мышкой и не кликая перемещаю курсор с одного элемента списка на другой, срабатывает OnIdle.
Как этого избежать? Т.е. Idle должен работать всегда, кроме момента, когда я работаю со списком.
Как не пытался задействовать фокусы у списка и даже формы ничего не получается. Приложение либо снимается, либо работает так, как описано выше.
PM ICQ   Вверх
mr.DUDA
Дата 4.1.2007, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

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



Цитата(Mal Hack @  4.1.2007,  20:52 Найти цитируемый пост)
Как этого избежать? Т.е. Idle должен работать всегда, кроме момента, когда я работаю со списком.

Дело в том, что Idle вызывается каждый раз когда приложение простаивает (нет ничего в очереди сообщений). Поэтому, чтобы отделять ситуацию "приложение не выполняет действий" от ситуации "ждём реакции пользователя", нужно либо:

1) Не использовать Idle
2) В обработчике Idle проверять некий флаг, который ставить в true в каждом месте, где может возникнуть ожидание без действий со стороны пользователя (aka без добавления сообщений в очередь сообщений)


--------------------
user posted image
PM MAIL WWW   Вверх
Mal Hack
Дата 4.1.2007, 22:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



2. Пытался такое сделать, но, в какой момент ставить флаг? На какиех двух событиях на комбобоксе это завязать?
Пробовал разное...
PM ICQ   Вверх
mr.DUDA
Дата 4.1.2007, 23:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

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



Событие DropDown - генерится при открытии раскрывающегося списка. Событие DropDownClosed - при закрытии.


--------------------
user posted image
PM MAIL WWW   Вверх
Mal Hack
Дата 4.1.2007, 23:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



mr.DUDA, возможен еще и такой вариант, что список будет юзаться не раскрываясь через клаву или колесико мышки...
PM ICQ   Вверх
mr.DUDA
Дата 4.1.2007, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

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



Цитата(Mal Hack @  4.1.2007,  22:27 Найти цитируемый пост)
mr.DUDA, возможен еще и такой вариант, что список будет юзаться не раскрываясь через клаву или колесико мышки...

Тогда ловим SelectedIndexChanged/SelectedItemChanged, но имхо это не то. Ведь юзер может долгое время просто ничего не делать - как это обрабатывать ? Забивать на Idle с момента получения фокуса комбобоксом smile ?

Какую задачу вообще нужно решить ? Если необходимо выполнять действия в фоне, то вполне подойдёт отдельный поток (System.Threading.Thread).


--------------------
user posted image
PM MAIL WWW   Вверх
Mal Hack
Дата 4.1.2007, 23:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



Цитата(mr.DUDA @  4.1.2007,  23:42 Найти цитируемый пост)
Какую задачу вообще нужно решить ?

Нужно проверять состояние одного сервиса, постоянно. И реагировать на это.

Цитата(mr.DUDA @  4.1.2007,  23:42 Найти цитируемый пост)
Забивать на Idle с момента получения фокуса комбобоксом smile ?

Пробовал. Не работает. Попозже попробую еще раз.
PM ICQ   Вверх
mr.DUDA
Дата 5.1.2007, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

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



Цитата(Mal Hack @  4.1.2007,  22:45 Найти цитируемый пост)
Нужно проверять состояние одного сервиса, постоянно. И реагировать на это.

Тогда отдельный поток - то что нужно.


--------------------
user posted image
PM MAIL WWW   Вверх
ivashkanet
Дата 5.1.2007, 11:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

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



Цитата(mr.DUDA @  5.1.2007,  08:51 Найти цитируемый пост)
Тогда отдельный поток - то что нужно.

Пример:
Код

public partial class Form1 : Form
    {
        private Thread _thread;

        public Form1()
        {
            InitializeComponent();
            StartListening();
        }


        private void StartListening()
        {
            if (_thread == null)
            {
                // Создаем новый поток и запускаем его
                _thread = new Thread(new ThreadStart(ListenServices));

                _thread.Start();
            }
            else
            {
                throw new Exception("Поток уже запущен");
            }
        }
        private void StopListerning()
        {
            if (_thread != null)
            {
                // Стопаем поток
                // Возбуждаем в методе потока ThreadAbortException
                _thread.Abort();
                // Ждем пока поток обработает исключение
                _thread.Join();

                _thread = null;
            }
            else
            {
                throw new Exception("Поток не запущен");
            }
        }

        private void ListenServices()
        {
            try
            {
                while (true)
                {
                    // будм считать, что LWS_UpdateInfo возвращает строку
                    // если она не пустая, то отображаем ее
                    string str = LWS_UpdateInfo();

                    if (str != "")
                    {
                        this.Invoke(new MethodInvoker(
                            // анонимный делегат, который поменяет значение Лабела
                            delegate()
                            {
                                this.label1.Text = str;
                            }
                        ));
                    }

                    Thread.Sleep(100); // останавливаем поток на 0.1 секунды :) 
                }
            }
            catch (ThreadAbortException)
            {/* просто возможность останова потока, возбуждением ThreadAbortException */}
        }

        private string LWS_UpdateInfo()
        {
            return DateTime.Now.ToString();
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            StopListerning();
        }



    }

PM MAIL WWW ICQ   Вверх
Mal Hack
Дата 5.1.2007, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



А это не будет сильно грузить систему?
пошел покупать книжку Шилдта...
PM ICQ   Вверх
mr.DUDA
Дата 5.1.2007, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

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



Цитата(Mal Hack @  5.1.2007,  14:55 Найти цитируемый пост)
А это не будет сильно грузить систему?

Выставишь задержку в потоке, и будет занимать вообще 0%


--------------------
user posted image
PM MAIL WWW   Вверх
Mal Hack
Дата 5.1.2007, 19:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



Окей. Спасибо... Пойду разбираться.
Ресурсы, которые кушает поток будут меньше, чем аналогичная реализация алгоритма через Timer?
PM ICQ   Вверх
mr.DUDA
Дата 5.1.2007, 22:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

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



Цитата(Mal Hack @  5.1.2007,  18:58 Найти цитируемый пост)
Ресурсы, которые кушает поток будут меньше, чем аналогичная реализация алгоритма через Timer?

Ну, в общем да; смотря какой таймер, кстати. Есть System.Windows.Forms.Timer, который работает через обычную очередь сообщений винды и WM_TIMER -- такой таймер будет пропускать тики до тех пор, пока есть необработанные сообщения в очереди, закинутые раньше чем тик; а есть System.Threading.Timer - он посылает свои события через ThreadPool. Что кстати не всегда подойдёт, т.к. в случае если обработка события таймера занимает бОльшее время, чем период таймера -- тогда события таймера будут накапливаться в очереди на обработку, вплоть до разбухания очереди до бесконечности. Поэтому, советую юзать класс Thread, с пом. которого запускать свой метод в отдельном потоке, и делать в этом методе любые действия, разделяя их паузой этак в 10-100 миллисекунд.

З.Ы. кстати, если нужно работать с контролами на форме из отдельного потока -- то см. пример от ivashkanet, где стоит коммент " анонимный делегат, который поменяет значение Лабела"...


--------------------
user posted image
PM MAIL WWW   Вверх
Mal Hack
Дата 5.1.2007, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



Не совсем понятно назначение этого анонимного делегата...
Реализовал через потоки. Работает. Попозже код положу.
PM ICQ   Вверх
mr.DUDA
Дата 5.1.2007, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

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



Цитата(Mal Hack @  5.1.2007,  21:54 Найти цитируемый пост)
Не совсем понятно назначение этого анонимного делегата...

Ну, это для того чтобы можно было работать с виндошными контролами (окна, текстбоксы, листбокс, и т.п.) из не-GUI потоков. Обычно, если пытаешься например изменить текущий item в комбобоксе из другого потока --  генерируется exception.


--------------------
user posted image
PM MAIL WWW   Вверх
Mal Hack
Дата 5.1.2007, 23:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



Цитата(mr.DUDA @  5.1.2007,  23:04 Найти цитируемый пост)
Ну, это для того чтобы можно было работать с виндошными контролами (окна, текстбоксы, листбокс, и т.п.) из не-GUI потоков. Обычно, если пытаешься например изменить текущий item в комбобоксе из другого потока --  генерируется exception. 

Ну т.к. я вызываю в этом месте метод, который работает с контролами, то сделал без делегата...

Код
        // while change selected service in ComboBox...
        private void cb_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cb.Text == "Не найдено сервисов." || cb.Text == "Выберите из списка.")
            {
                lblServiceNameInfo.Text = "";
                lblServicePathInfo.Text = "";
                lblServiceStatusInfo.Text = "";

                this.thrStopListening();
                return;
            }

            LWS_UpdateInfo();
            thrStartListening();
        }

        // Disable Service Listening when click on ComboBox
        private void cb_Click(object sender, EventArgs e)
        {
            this.thrStopListening();
        }

        private void LWSForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            thrStopListening();
        }

        private void thrStartListening()
        {
            if (_thread != null)
            { return; }

            _thread = new Thread(new ThreadStart(thrListen));
            _thread.Start();
        }

        private void thrStopListening()
        {
            if (_thread == null)
            { return; }

            _thread.Abort();
            _thread.Join();
            _thread = null;
        }

        private void thrListen()
        {
            try
            {
                while (true)
                {
                    LWS_UpdateInfo();
                    Thread.Sleep(500);
                }
            }
            catch (ThreadAbortException)
            { }
        }

PM ICQ   Вверх
ivashkanet
Дата 6.1.2007, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

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



Цитата(Mal Hack @  5.1.2007,  22:21 Найти цитируемый пост)
Ну т.к. я вызываю в этом месте метод, который работает с контролами, то сделал без делегата...

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

Попытаюсь объяснить почему именно так (один раз попробовал, но меня не поняли smile smile ):

Главная проблемма потоков в том, что они работают одновременно один себе, второй себе, но могут использовать один и тот же объект (например тот же Лабел). 
Если они только читают информацию, то это все равно. Один прочитал, тут же второй  -- никаких проблемм. 

Но вот если один из них вздумает изменить, тут начинаются проблеммы.

Представим себе такую жизненную аналогию этой ситуации:
У нас есть два ученика (два потока) и школьная доска (это объект с которым взаимодействуют эти потоки).
На доске написано: "Мама мыла раму".
Оба ученика с легкостью могут читать это сообщение, не заботясь о том, что кто-то так же читает это же сообщение.

Но представьте себе ситуацию, когда первый ученик прочитал первую часть сообщения "Мама мыла", а второй тут же заменил сообщение на "Ехали медведи на велосипеде", о чем второй даже не догадывается. 

Что получится? Что-то типа "Мама мыла на велосипеде"  --- бред? -- Да. Первый ученик будет в непонятнках (если он умный) или будет дальше использовать это предложение, считая что это нужное ему сообщение (если не совсем умный).

Смысл, я надеюсь ясен smile
Если вам интересно, как может такое случиться, что второй не заметит замену сообщения, то вас ждет приложение 1

Для разрешения этой ситуации придумано много методов:
1) Класс Threading.Monitor, который специально предназначен для разруливания таких ситуаций
2) конструкция (которая внутри себя используют именно Monitor).
Код

lock(someObject)
{

}

3) Для UI (user interface) Майкрософт решила использовать (начиная со второй версии фрэймворка) еще один принцип:
Изменять объекты UI может только один единственный поток --- UI-thread, который создается вместе с любой формой, и который обрабатывает системные сообщения.

В свете нашей аналогии пусть это будет учитель. И только учитель может писать на доске.
А для того, чтобы ученик мог изменять состояние доски используются просьбы к учителю:
"Марь Иванна, напишите на доске "Ехали медведи на велосипеде", пожалуйста".
Или в терминах .Net 
Код
control.Invoke(doSomethingDelegate);


Насколько это решает проблеммы? ИМХО, так себе. 
Проблему с одним учителем и одним учеником -- да, а вот если учеников будет два, то нет smile 
Но сейчас не об этом.

С проблемой, ИМХО, закончили. Теперь о том, почему я считаю, что вызов метода внутри метода не решит проблемму:
Что такое метод --- это всего лишь инструкция исполнителю. Этой инструкции совершенно все равно кто будет ей следовать.
Поэтому если первый ученик (поток) будет следовать ей, а в середине увидит, что нужно взять другую инструкцию, то именно он будет ей следовать, а не кто-то другой.

Вот такие вот дела smile

Приложение 1
Немного теории распределения процессорного времени между потоками:
Скажу сразу, что на полную достоверность я не претендую, но смысл будет передан верно, ИМХО.
На однопроцессорной машине в один момент времени может выполняться только одна инструкция.
Как же тогда достигается паралельность выполнения задач, спросите вы.
Дело в том, что никакакая это не паралельность, а псевдопаралельность
Достигается это тем, что процессор постоянно используется разными процессами/потоками поочередно. Сначала первый, потом второй, третий, потом опять первый. В зависимости от приоретета потока. И промежутки времени настолько малы, что мы не можем заметить это переключение, для нас действия выполняются одновременно.
И совершенно неизвесно, когда операцианная зистема заморозит выполняющийся поток и передаст управление новому. 
Это может быть в любой момент выполнения длинного действия (изменении надписи).
Именно поэтому первый "ученик" может заснуть на середине прочтения надписи, а второй в это время изменить ее.

P.S. Делегат -- это просто безопасная ссылка на метод (инструкцию). Ссылка на адрес в памяти, по которомы написана инструкция.
PM MAIL WWW ICQ   Вверх
Mal Hack
Дата 6.1.2007, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



Цитата(ivashkanet @  6.1.2007,  14:52 Найти цитируемый пост)
Немного теории распределения процессорного времени между потоками:

Это  я знал.

Так, в принципе понятно, но... Получается так, что при выполнении двух потоков, один может заснуть, а второй создаст делегата и будет изменять контролы, в то время как первый до делегата не дошел. В таком случае проблема актуальна?
Или псевдорапараллеливание устроено таким образом, что процесс может заснуть только унутри делегата, а не перед while'ом и т.п.? Хотя мне в это верится как-то с трудом.

Сделал с делегатом... приложение подисает после энного кол-ва изменения выбранного элемента комбобокса smile)
PM ICQ   Вверх
ivashkanet
Дата 6.1.2007, 20:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

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



Цитата(Mal Hack @  6.1.2007,  14:22 Найти цитируемый пост)
Это  я знал.

Это только для того, чтобы описываемая картина была более менее полна smile
Цитата(Mal Hack @  6.1.2007,  14:22 Найти цитируемый пост)
Получается так, что при выполнении двух потоков, один может заснуть, а второй создаст делегата и будет изменять контролы, в то время как первый до делегата не дошел. В таком случае проблема актуальна?

Увы да smile
По мне, эта каша с "изменять объекты UI может только один единственный поток --- UI-thread" заварена только для того, чтобы обезопасить систему. Мало ли как можно повлиять на виндовые процессы, может даже на ядро системы через UI (это только догадки  smile ).

Самый главный принцип разруливания совмесной работы с двумя потоками заключается в использовании Threading.Monitor или его "обертки" lock.

Если по простому, то никакой второй поток не может зайти внутрь lock-блока, если внутри уже есть другой. Он будет терпеливо ждать за пределами блока.
Кроме того, если мы написали lock в двух местах (в двух разных частях программы) с одним и тем же аргументом (забыл как называется, что-то типа "объект синхронизации"), то если поток зашел внутрь в одном месте, то второй поток не сможет зайти внутрь блоков ни в первом, ни во втором месте.
Пример с lock есть в ФАКе спасибо Доместиксу  smile 

Цитата(Mal Hack @  6.1.2007,  14:22 Найти цитируемый пост)
Сделал с делегатом... приложение подисает после энного кол-ва изменения выбранного элемента комбобокса 

Ну так под отладку его. Нажимаешь паузу и смотришь в каком месте застопорился главый поток формы smile

Добавлено @ 20:06 
P.S. Прошу прощение за смазанность первого сообщения. Не рассчитал время и не успел. Были дела. Попытаюсь дополнить.
PM MAIL WWW ICQ   Вверх
Mal Hack
Дата 6.1.2007, 20:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



Thread.Sleep(100); распространяется на все процессы, которые запущены?
PM ICQ   Вверх
ivashkanet
Дата 6.1.2007, 20:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

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



Цитата(Mal Hack @  6.1.2007,  19:29 Найти цитируемый пост)
Thread.Sleep(100); распространяется на все процессы, которые запущены?

Нет, только на тот, кто этот метод вызывает smile
PM MAIL WWW ICQ   Вверх
Mal Hack
Дата 6.1.2007, 21:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



Хм... Вот есть:
Код

        private Thread _thread;
        private Thread _threadStart;

Тот, который _thread запущен и работает практически постоянно.
Код
        private void thrListen()
        {
            try
            {
                while (true)
                {
                    LWS_UpdateInfo();
                    Thread.Sleep(100);
                }
            }
            catch (ThreadAbortException)
            { }
        }

Второй запускается в нужный момент, что-то делает и отключается:
Код
        private void thrServiceBeginRun()
        {
            this.Invoke(new MethodInvoker(
                delegate()
                {
                    ServiceControl.Start();
                    ServiceControl.Refresh();

                    while (ServiceControl.Status.ToString() != "Running")
                    {
                        ServiceControl.Refresh();
                        Thread.Sleep(1000);
                    }

                    LWS_UpdateInfo();
                    cb.Enabled = true;
                    this.thrServiceEnd();
                }
            ));
        }

Во время выполнения второго потока, первый, который вызываем LWS_UpdateInfo как бы перестает работать, что не есть хорошо... Как это можно исправить?
PM ICQ   Вверх
ivashkanet
Дата 6.1.2007, 22:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

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



Mal Hack, у тебя чуть чуть неправильный код. 
Ты "доверил" UI потоку слишком много работы. 
Он должен только обновить контролы, а не ждать еще остановки сервиса. 
Ведь тогда он (UI поток) не сможет отвечать на запросы пользователя, т.е. 
Цитата(Mal Hack @  6.1.2007,  14:22 Найти цитируемый пост)
 приложение подисает после энного кол-ва изменения выбранного элемента комбобокса

Предлагаю сделать так:
Код

        private void thrServiceBeginRun()
        {
            ServiceControl.Start();
            ServiceControl.Refresh();

            while (ServiceControl.Status.ToString() != "Running")
            {
                 ServiceControl.Refresh();
                        Thread.Sleep(1000);
            }

            this.Invoke(new MethodInvoker(
                delegate()
                {
                    LWS_UpdateInfo();
                }
            ));

            cb.Enabled = true;
            this.thrServiceEnd();
        }

PM MAIL WWW ICQ   Вверх
ivashkanet
Дата 6.1.2007, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

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



Кстати, так как метод LWS_UpdateInfo() полностью соответствует требованиям MethodInvoker-делегата (не имеет прараметров), то можно обойтись без анонимного делегата.
Т.е. так:
Код

this.Invoke(new MethodInvoker(LWS_UpdateInfo()));

PM MAIL WWW ICQ   Вверх
Mal Hack
Дата 6.1.2007, 23:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



Цитата(ivashkanet @  6.1.2007,  22:47 Найти цитируемый пост)
Он должен только обновить контролы, а не ждать еще остановки сервиса. 

А ServiceControl в их число не входит?
Т.е. грубо говоря, надо использовать делегата, когда пытаешься изменить свойства визуальных объектов?

Так. Вроде бы с этим разобрался... Осталось вот что.
Код

        private void thrServiceBeginRun()
        {
            ServiceControl.Start();
            ServiceControl.Refresh();

            while (ServiceControl.Status.ToString() != "Running")
            {
                ServiceControl.Refresh();
                Thread.Sleep(1000);
            }

            this.Invoke(new MethodInvoker(
                delegate()
                {
                    LWS_UpdateInfo();
                    cb.Enabled = true;
                }
            ));

            this.thrServiceEnd();
        }

А очень надо. thrServiceBeginRun - фукция висит в потоке. После завершения работы, она должна поток удалить. Но этого не происходит.
Устанвлено, что this.thrServiceEnd(); -  не выполняется. 
PM ICQ   Вверх
Mal Hack
Дата 7.1.2007, 00:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



Проблему решил банально. this.thrServiceEnd(); заменяем на _threadStart = null;
PM ICQ   Вверх
ivashkanet
Дата 7.1.2007, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

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



Цитата(Mal Hack @  6.1.2007,  23:09 Найти цитируемый пост)
this.thrServiceEnd()

А можно увидеть код этой функции?
Цитата(Mal Hack @  6.1.2007,  23:09 Найти цитируемый пост)
_threadStart = null;

Это выражение, по сути, только теряет ссылку на поток, после чего сборщик мусора его съест.
Но вот когда это будет?
Я бы внутри thrServiceEnd сделал _threadStart.Abort() , _threadStart.Join()б а только потом гасил ссылку
Цитата(Mal Hack @  6.1.2007,  22:12 Найти цитируемый пост)
Т.е. грубо говоря, надо использовать делегата, когда пытаешься изменить свойства визуальных объектов?

Ага. 
Mal Hack, ты попробуй удалить делегата. Если получишь Exception, то он был нужен, если нет то нет smile
PM MAIL WWW ICQ   Вверх
Mal Hack
Дата 7.1.2007, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



Цитата(ivashkanet @  7.1.2007,  14:29 Найти цитируемый пост)
Я бы внутри thrServiceEnd сделал _threadStart.Abort() , _threadStart.Join()б а только потом гасил ссылку

Как раз это там и есть.
PM ICQ   Вверх
ivashkanet
Дата 7.1.2007, 15:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

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



Цитата(ivashkanet @  7.1.2007,  13:29 Найти цитируемый пост)
Я бы внутри thrServiceEnd сделал _threadStart.Abort() , _threadStart.Join()б а только потом гасил ссылку

Да это не нужно делать smile У нас же не бесконечный цикл из которого нужно выходить Exception-ом.

У нас этот метод вызывается внутри нашего потока  smile 
Именно поэтому аборты и джоины не нужны smile
В принципе ничего не надо делать. Поток завершит работу по окончанииметода smile

P.S. Mal Hack, ну и намудрил ты, гы. Нее, все нормально, но я, просто, не сразу понял твою логику. Не заметил, что thrServiceBeginRun --- это основной метод потока smile Мнея спутало его название

Это сообщение отредактировал(а) ivashkanet - 7.1.2007, 15:16
PM MAIL WWW ICQ   Вверх
Mal Hack
Дата 7.1.2007, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


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

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



Цитата(ivashkanet @  7.1.2007,  15:13 Найти цитируемый пост)
P.S. Mal Hack, ну и намудрил ты, гы.

Я интуитивно дошел до этого smile)
PM ICQ   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

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


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

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


 




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


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

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