Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Ожидание события  (Прочитано 1963 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Serguntii
Помогающий

ru
Offline Offline

« : 27-11-2013 18:34 » 

Никак не соображу как сделать,  нужно ждать когда установиться переменная start сразу после этого ее сбросить  и вызвать функцию.
Использовать for все зависает. Если использовать в отдельном потоке,  то вылетают ошибки: обращение  к контролу (label textbox...) из другого потока. 
Код:

class mycl{
public bool start;
mycl()
{
start = false
}


void watstart()
{

for(;;)
{
if(start)
{
start = false;
 mymetod()
}

}
}


void mymetod()
{


}



}


Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 27-11-2013 19:47 » 

Использовать симофоры, как один из вариантов.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 27-11-2013 20:44 » 

sergeyan, ненужные сложности. Создай поток и стартуй его по необходимости. Только не зацикливай его внутри, это пустая трата процессорного времени. И да, синхронизация в многопоточности для общих ресурсов обязательна.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 27-11-2013 20:54 » 

Допустимо преобразовать start из переменной в свойство? Если да, то тогда заставить мутатор генерировать событие, а подписчик этого события в свою очередь вызовет нужную функцию. Все необходимое уже есть в .NET, к тому же механизм событий не расточает ресурсы во время ожидания.

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

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Serguntii
Помогающий

ru
Offline Offline

« Ответ #4 : 27-11-2013 21:44 » 

Придется синхронизировать, думаю сделать через invokerequired придется добавлять еще код .
А как запустить backgroundworke  что бы dowork работал постоянно у меня он выполняется только один раз. запускаю его .RunWorkerAsync();
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 27-11-2013 22:52 » 

В .NET есть ManualResetEvent и AutoResetEvent. Это как раз объекты синхронизации для таких случаев. Оба работают таким образом, что если флаг события стоит, то любые операции Wait не ждут. Если же флаг события сброшен, то любые операции Wait останавливают вызвавший их поток до установки флага. Разница между ними в том, что в первом случае флаг нужно сбрасывать вручную - т.е. если на ожидании висит много потоков, они все или несколько из них могут пройти Wait, прежде чем один из них сбросит флаг; во втором случае факт прохождения одного потока приводит к автоматическому сбрасыванию флага, и потоки могут проходить через ожидание события строго по очереди.

Однако из формулировки задачи судя по жалобе на зависания вовсе неясно, что код с циклом выполняется в отдельном потоке, и что это именно так нужно. Поэтому присоединяюсь к предложению Dale рассмотреть возможность создания собственного события, которое срабатывает при каком-то условии (кстати, непонятно, что это? started - уже/ранее запущенный, starting - запускающийся, startRequired - требующий/запрашивающий запуска). И, соответственно, все желающие могут на это событие подписаться. Возможно даже и переменной не понадобится, если подробно описать задачу.

Что касается фонового исполнения, то упомянутый background work - это лишь обёртка над банальным потоком (скорее всего из системного пула потоков), у которого установлено свойство IsBackground. Отличается он от обычного потока тем, что не способен удерживать процесс в работающем состоянии. Т.е. как только в процессе закончили работу все обычные потоки, фоновые потоки уничтожаются автоматически. Это накладывает на фоновые потоки некоторые ограничения: например, не стоит в них работать с какими-то критическими ресурсами, требующими корректного освобождения. Кроме того, фоновые потоки работают с более низким приоритетом, чем обычные. Ну и поскольку речь идёт о потоке, то, разумеется, окончание работы процедуры потока приводит к завершению самого потока. Таким образом, претензии "только один раз работает" не принимаются: цикл писать всё равно нужно. Альтернативными циклу вариантами являются использование периодического запуска по таймеру и создание схемы каскада асинхронных вызовов (аналог рекурсивного вызова функции, только из-за асинхронного характера не накапливается стек вызовов).

По поводу того, что работает или не работает Label. Элементы пользовательского интерфейса - будь то Windows.Forms или WPF - работают в модели STA, и я понятия не имею, каким боком в недрах .NET проявляются эти вещи, унаследованные от COM. Но суть в том, что в STA модели доступ к объектам имеет только один поток - тот, в котором они созданы, и это позволяет не заботиться о синхронизациях и в общем-то ускоряет работу. Именно поэтому попытка прямого обращения к Label и любому другому элементу пользовательского интерфейса из другого потока просто как к объекту в памяти закончится плачевно. Чтобы выполнять эту работу в WPF существует специальный объект Dispatcher (доступный через свойство любого элемента пользовательского интерфейса), через который осуществляется marshaling вызовов между потоками. В частности, из одного потока можно синхронно или асинхронно выполнить код, работающий с данными другого потока. В случае синхронного вызова это происходит так: главный поток пользовательского интерфейса, разумеется, крутится в главном цикле приложения - обрабатывает сообщения Windows; когда другой поток делает вызов, он переходит в режим ожидания отклика главного потока; главный поток, когда заканчивает обработку очередного сообщения и переходит в состояние анализа следующего задания/сообщения, обнаруживает в очереди запрос к себе и выполняет код запроса, после чего продолжает работать в цикле; вызывающий поток, получив результат обработки запроса, тоже продолжает работу. В случае асинхронного вызова вызывающий поток не ждёт ничего такого, а просто продолжает работу, оставив свой запрос в очереди на исполнение главного потока. Реализуется это через стандартный шаблон асинхронного вызова Begin-End.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines