Форум программистов, компьютерный форум, киберфорум
Наши страницы

C# Windows Forms

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 16, средняя оценка - 4.81
JustOneQuestion
0 / 0 / 0
Регистрация: 01.05.2015
Сообщений: 84
#1

Ожидание события. Как правильно? - C#

22.09.2015, 23:56. Просмотров 3922. Ответов 43
Метки нет (Все метки)

Здравствуйте.
Язык C#. (Проект не помню точно как создавал. Но что-то по умолчанию с формами и без излишеств.)
Есть одна форма. На неё добавлены 3 элемента: Кнопка, COMпорт и таймер.
По нажатию на кнопку запускается некая функция (попутно запускается таймер и предполагается что по COMпорту что-то может прийти). И вот в процессе выполнения этой функции надо поставить её на паузу до тех пор пока либо таймер не сработает либо байт с порта не прийдёт. Сделал я вот таким способм.

Кусок этой самой функции, там где она собственно должна быть на паузе.
C#
1
2
3
4
5
6
7
8
9
10
.....
IsAnswered=false;
OutOfTime = false;
this.timer1.Enabled = true;
this.timer1.Start();
while ((!OutOfTime) && (!IsAnswered))
 {
     Application.DoEvents();//Ждём ответа.
 }
.....

И Также есть обработчики таймера и порта.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  private void timer1_Tick(object sender, EventArgs e)
        {
            this.timer1.Stop();
            this.timer1.Enabled = false;
            OutOfTime = true;
        }
 
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            int CurByte;
 
            this.timer1.Stop();
            this.timer1.Enabled = false;
            OutOfTime = false;
            IsAnswered = true;
        }
И всё вроде хорошо работает. Но цикл вместо спячки?!...Ну это както совсем не правильно. А вот как Правильно сделать? )
Что-то вроде
C++
1
2
3
4
HANDLE waitArray[2] = {event1, event2};
DWORD waitResult = WaitForMultipleObjects(2, waitArray, FALSE, INFINITE); //вместо цикла
//и 
SetEvent(event1);//в обработчике таймера и порта
можно на C# сделать? Но только без импорта дллелек... А как-то C#-ким методом.

Спасибо за внимание.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
22.09.2015, 23:56
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Ожидание события. Как правильно? (C#):

Как правильно удалять события - C#
Как правильно удалять события в данном случае, ибо каждое добавленное событие сохраняется. Целесообразно ли использовать IDisposable и в...

Ожидание нажатия события контрола - C#
ситуация такая : есть метод в котором имеется некий цикл, мне нужно что бы в этом цикле, в определенном месте кода, ожидалось нажатие на...

Как правильно использовать события и свойства элемента CheckBox - C#
Как получить обратное действие? Например у меня на форме: checkBox1 textBox1 Мне нужно чтобы когда была галочка (Что введенно...

Сделать ожидание события клика на программно созданных pictureBox - C#
Как сделать ожидание события клика на программно созданных pictureBox? Пробовал через Sleep, но он подгружает программу, не кликнуть, не...

SerialPort: Ожидание События или получение ответа из потока чтения флуда байтов - C#
Имеется: OpenPort() - открывает порт и любимый Поток readport() - Поток который считывает всё, всегда и везде lan() - метод который...

Как в одном обработчике события запустить другой обработчик события - C#
Есть список listView1, который заполняется из массива PeopleListprivate void listView1_RetrieveVirtualItem(object sender,...

43
EvilFromHell
944 / 843 / 267
Регистрация: 26.04.2012
Сообщений: 2,648
11.10.2015, 01:40 #31
Какое-то время не смотрел тему... Воркер-это обертка над тем же потоком, суть от этого не сильно изменяется. Инвоков там не нужно писать только потому, что они происходят внутри. Как подождать в потоке-в теме уже предложили 2 варианта-либо EventWaitHandle(или его наследники,как в вашем случае), либо использовать вместо потоков асинхронность. Если есть желание - ничто не мешает оформить все это в виде очереди сообщений, создать эту самую очередь и при добавлении элемента будить поток, а когда все сообщения обработаны-опять его усыплять. В вашем же коде потоков 3 и все в одном классе, что не соответствует поставленной задаче.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
PostMessage без ImportDLL не работает
Что же мешает написать этот самый импорт?
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
а event... это вобще обман сплошной
Это говорит лишь о том, что вы не понимаете, как его использовать. К потокам event не имеет никакого отношения-это для эффективной передачи данных между классами.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
чтобы действительно в очередь формы попадало и в форме делалось а не абы где...
Опять же-эта задача элементарно решается инвоками... чего вы их так невзлюбили-совершенно не понимаю
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Task
Это не совсем обычный поток. Это задача, какая выполняется в потоке из ThreadPool(про различие), классический поток-это Thread.
0
JustOneQuestion
0 / 0 / 0
Регистрация: 01.05.2015
Сообщений: 84
11.10.2015, 08:19  [ТС] #32
Как я уже говорил, по хорошему надо чтобы программа была в одном потоке, а форма в другом и что бы они были по максимуму независимы. Форма нужна только чтобы не в консоль выводить какието сообщения, данные и прочее что навычисляет программа, ну и чтобы считывать какието данные от пользователя. В форму допустимо засунуть функции для проверки вводимых данных от пользователя и преобразования в удобочитаемый формат того чтобы выдаст основная программа. Можно ещё добавить в форму что-то что явно независимо от всей остальной программы может происходить. Например если музыкальный проигрыватель делать. В основном потоке всё будет насчитываться и отправляться в буфера аудо устройств. А вот в форму можно добавить плей-лист. Форма может проверять файлы на правильный формат, удалять или добавлять в список новые треки. А слать она будет уже тока сообщения в главный поток о том что пользовтель тыкнул плей и сказать что же именно он захотел просулашать. Писать же весь код в обработчиках события формы это может и можно... но как-то очень не правильно, просто в силу того что UI и основной код в одном месте при разрастании обоих превращается в жуткого неповоротливого монстра.
PostMessage в C# в явном виде я не нашел.. Чему был очень удивлён. Но PostMessage всё же штука специализированная, заточенная под окна. WaitHandle же более универсален. Более того он не только межпотоковый но и межпроцессовый может быть. PostMessage конечно тоже межпотоковый, но через WaitHandle можно и не только с окнами работать. Хотя.. если покопаться то возможно получится что PostMessage на WaitHandle или чем-то подобном реализован.
В моём примере не совсем 3 потока. Поток формы - раз. Поток (а точнее пул потоков) BGworkera - два. А третий это поток в котором делается основной код и который взаимодействует с формой самым минимальным и необходимым образом. Нет смысла код засовывать в BGworker по причине которую я уже описал выше - хорошо всё таки код и UI разделять по максимуму.

Invoke не смертельно конечно. Кроме одного НО. Он возникает только в том случе, когда мы пытаемся напрямую достучаться до контролов из другого потока. А это явный признак того что UI и основной код программы не полностью разделены. Вот когда мы используем делегаты, то мы код, который должен быть по идее в потоке UI, начинаем исполнять в потоке основного кода программы, вот тогда и возникает необходимость инвоков. Тоесть инвоки это не проблемма. Проблемма это наличие причины по которой эти инвоки надо использовать.

event это что называется трудности перевода.
Event wait handles are not events in the sense usually meant by that word in the .NET Framework. There are no delegates or event handlers involved. The word "event" is used to describe them because they have traditionally been referred to as operating-system events, and because the act of signaling the wait handle indicates to waiting threads that an event has occurred.
https://msdn.microsoft.com/en-us/lib...0%28English%29
Вобщем event он дейтсвительно вовсе не для ГЕНЕРАЦИИ и ЧТЕНИЯ событий нужны. И тут явно путаница возникает, так как event к реальным событиям отношения не имеет. Это виртуальный обман. Подписываемся в одном месте, вызываем в другом и кажется что один вызвал "событие" а второй на него отреагировал... По сути же вызывает и раегирует одни и тотже, но правда то что он делает вовсе не его работа). Да , для взаимодействия между классами это может и нужно. Но к раельным события этом не имеет никакого отношения. А то что назвали event'ом ... ну я даже неа знаю как это объянсить.. это прям диверсия и вредительство.

А что касается Task то принципиального различия нет - это тоже просто другой поток. Разница лишь в том как оно создается, поддерживается и убивается. BGworker тоже например пул а не просто поток.

Но собственно почему BGworker? Дело не в том, что там инвоки писать не нужно) .. Дело в том что он умеет генерировать событие в очередь формы. Тоесть он работает как PostMessage по сути. А вот как кроме этих способов я не знаю как добавить в очередь формы пользовательские события. Я про это и спрашивал. Просто если не добавлять прям в очередь событий формы своё событие, то вроде как ни крути а исполняться код будет не в потоке формы а гдето-то у нас в коде. А это как я уже несколько раз повторял не хорошо.
0
EvilFromHell
944 / 843 / 267
Регистрация: 26.04.2012
Сообщений: 2,648
11.10.2015, 19:31 #33
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Как я уже говорил, по хорошему надо чтобы программа была в одном потоке, а форма в другом и что бы они были по максимуму независимы.
Отделение UI от логики должно состоять в первую очередь в разделении на классы. А между классами должны быть eventы. Если какое-то событие может вызываться в другом потоке, то расставить инвоки, только и всего. Не вижу тут никаких логических противоречий и трудностей.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Дело в том что он умеет генерировать событие в очередь формы.
Я вот сколько читаю, так и не понял, что же это за очередь такая. Знаю очередь оконной процедуры у формы, туда воркер по идее ничего кидать не должен и использует он те же самые eventы. Практическая разница как раз таки в том, что не надо писать инвоки остальное все тонкости реализации.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Invoke не смертельно конечно. Кроме одного НО. Он возникает только в том случе, когда мы пытаемся напрямую достучаться до контролов из другого потока. А это явный признак того что UI и основной код программы не полностью разделены. Вот когда мы используем делегаты, то мы код, который должен быть по идее в потоке UI, начинаем исполнять в потоке основного кода программы, вот тогда и возникает необходимость инвоков. Тоесть инвоки это не проблемма. Проблемма это наличие причины по которой эти инвоки надо использовать.
Не вижу тут никакой проблемы. ООП-то для чего придумано? Все разделение успешно реализуется с его помощью.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
И тут явно путаница возникает, так как event к реальным событиям отношения не имеет.
Ну в терминологии .NET эти события вполне "реальны" Если этим словом в другом месте называют что-то другое, то это совершенно не означает, что тут есть какой-то "обман".
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
А что касается Task то принципиального различия нет - это тоже просто другой поток. Разница лишь в том как оно создается, поддерживается и убивается. BGworker тоже например пул а не просто поток.
Да, тут все верно. Правда, если использовать не Task.Run, а async/await, то там все несколько сложнее.
Кстати говоря, отличный пример с использованием воркера в тему уже давно выложил insite2012, почему вы не взяли на вооружение его?

Добавлено через 12 минут
В целом проблема, на мой взгляд, заключается в том, что вы мыслите понятиями из низкоуровневого программирования, а не ООПшными. Что для данного языка совершенно не подходит.
0
JustOneQuestion
0 / 0 / 0
Регистрация: 01.05.2015
Сообщений: 84
12.10.2015, 06:37  [ТС] #34
Отделение UI от логики должно состоять в первую очередь в разделении на классы. А между классами должны быть eventы. Если какое-то событие может вызываться в другом потоке, то расставить инвоки, только и всего. Не вижу тут никаких логических противоречий и трудностей.
Если считать что отделение UI от логики должно быть только в классах, то действительно использовние eventов ни чему не противоречит. Другое дело что загружать поток логики вопросами UI далеко не всегда разумно. Взять хотябы пример если логика на серевере где-то делается. Заставлять тогда сервер обрабатывать код клиенткого UI уже не так логично. Или даже на одном компе, если UI довольно громоздкое, (что вполне себе может быть) а его обработка весьма трудоёмкая, то есть 2 варианта: тормозит всё и логика и UI(так как всё всемете обрабатывается); тормозит только UI а логика обрабатывается сама по себе, и принимает от UI только то, что UI успело насчитать(далеко не все события UI есть смысл обрабатывать, например при перемещении курсора нет надобности каждую "миг" обрабатывать изменение курсора мышки). Ну и ещё один, как мне кажется, очень важный пример, это возможность использовать UI и основную программу в разных процессах - тогда основной код и UI могут писать абсолюбтно разные люди на разных языках (согласитесь что форму на шарпе написать удобнее чем на голых C, а основную программу, иногда разумнее НЕ писать на шарпе). Плюс если процессы UI и основной логики разные, но есть некоторый оговоренный способ взаимодействия, то можно написать ещё и ешё различные реализации модулей UI и использовать тот или иной модуль как вам захочется. Вот это и есть максимальная независимость UI и основого кода программы.

Я вот сколько читаю, так и не понял, что же это за очередь такая. Знаю очередь оконной процедуры у формы, туда воркер по идее ничего кидать не должен и использует он те же самые eventы. Практическая разница как раз таки в том, что не надо писать инвоки остальное все тонкости реализации.
Есть два потока. В одном из них что-то выполняется, но тут вдруг нам приспичило чтобы в этом потоке срочно исполнилось что-то ещё, причем Когда и Что становится ясно только во время испольнения второго потока, но он ооочень занят и надо чтобы это сделал первый поток. Из самых общий соображений можно устроить принудительное прерывание (interupt) первому потоку с push-pop'ами, но это очень суровый метод. Есть другой вариант - первый поток регулярно в вечном лупе или по таймеру опрашивает второй поток на вопрос "есть чё мне для тебя сделать?". И есть ещё один вариант, когда первый поток сделав работу спит и никого не о чём не спрашивает, но у него есть возможность проснуться от сообщения что пора работать, притом, если первый и так работал, а ему ещё от второго пришло задание, и ещё потом, то он должен не проигнорировать, а записать в Очередь то, что ему надовали делать. Вот чтобы второй поток мог дать работу первому, надо чтобы либо первый сам опрашивал, либо имел возможность пробудиться. А это возможно только если у первого реализован способ добавления задач в очередь (журнал работ с карандашиком в который ему записывают что нужно будет сделать когда будет свободное время) либо если он опрашивает сам остальных. Опрос остальных не очень удобен - работодателей может быть много.. да и не всегда они работу дают, и тратить время на опрос особо нет хочется. (В принципе МОЖНО КОЕНЧНО опрашивать это вполне допустимо, более того иногда это единственный возможный вариант) В итоге было бы хорошо чтобы у первого потока был журнал заданий.. и Очередь ) Вот в Форме как раз и есть нечто подобное. Пришло событие от клавы или мышки - форма обработкала. Ну в самом деле, не драйвер же клавы этим занимается ) Всё же обработка клика мышки это работа потока формы... Зуб не дам, но я разочаруюсь совсему уже в Винде если узнаю что это не так.

Ну в терминологии .NET эти события вполне "реальны" Если этим словом в другом месте называют что-то другое, то это совершенно не означает, что тут есть какой-то "обман".
НУ.. вот виртуальная машина (с линуксом на компе с виндой) это обман? )

Кстати говоря, отличный пример с использованием воркера в тему уже давно выложил insite2012, почему вы не взяли на вооружение его?
Вот тут вот я должен ещё раз сказать всем ВАМ спасибо и insite2012 и EvilFromHell и wm_leviathan, за ваши советы. Собственно именно прочитав их я понял куда нужно смотреть в мсдн и про что читать, и по сути именно из всех ваших примеров я и получил свой вариант.

А что касается ООП и низкоуровневого программирования, то, в силу того что в ООП я действительно плохо рабираюсь, то сравнивать их я не могу. Но на мой взгляд общая логика построения устройства или программы не должна зависеть от языка программирования. Но вот реализация то конечно зависит, и не всем языкам та или иная логика (архитектура, общий смысл) доступна для реализцаии.
0
EvilFromHell
944 / 843 / 267
Регистрация: 26.04.2012
Сообщений: 2,648
12.10.2015, 07:49 #35
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Вот это и есть максимальная независимость UI и основого кода программы.
Еще раз повторю-шарп-это ООП язык. А вы пытаетесь навязать этому языку чуждую ему концепцию Это все было бы абсолютно верно, если бы речь шла про язык, который не поддерживает ООП, но не тут. Суть в том, что, согласно принципам инкапсуляции, в классе, который отвечает за UI, ничего кроме UI и не должно выполняться. Вся логика должна обрабатываться в другом классе, ссылка на объект которого кидается в UI, в UI же надо просто подписаться на эвенты и дергать методы того объекта. Если эвенты поступают из другого потока-ничто не мешает расставить инвоки. А вот в классе, который отвечает за логику, как раз таки для длительных операций надо запускать потоки, а сложить 2 числа можно и в том же потоке, где UI-больше расходов будет на создание потока, чем на само действие. Именно по этой логике написаны оба варианта, какие я и insite2012 предлагали в теме.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Есть два потока. В одном из них что-то выполняется, но тут вдруг нам приспичило чтобы в этом потоке срочно исполнилось что-то ещё, причем Когда и Что становится ясно только во время испольнения второго потока, но он ооочень занят и надо чтобы это сделал первый поток. Из самых общий соображений можно устроить принудительное прерывание (interupt) первому потоку с push-pop'ами, но это очень суровый метод. Есть другой вариант - первый поток регулярно в вечном лупе или по таймеру опрашивает второй поток на вопрос "есть чё мне для тебя сделать?". И есть ещё один вариант, когда первый поток сделав работу спит и никого не о чём не спрашивает, но у него есть возможность проснуться от сообщения что пора работать, притом, если первый и так работал, а ему ещё от второго пришло задание, и ещё потом, то он должен не проигнорировать, а записать в Очередь то, что ему надовали делать. Вот чтобы второй поток мог дать работу первому, надо чтобы либо первый сам опрашивал, либо имел возможность пробудиться. А это возможно только если у первого реализован способ добавления задач в очередь (журнал работ с карандашиком в который ему записывают что нужно будет сделать когда будет свободное время) либо если он опрашивает сам остальных. Опрос остальных не очень удобен - работодателей может быть много.. да и не всегда они работу дают, и тратить время на опрос особо нет хочется. (В принципе МОЖНО КОЕНЧНО опрашивать это вполне допустимо, более того иногда это единственный возможный вариант) В итоге было бы хорошо чтобы у первого потока был журнал заданий.. и Очередь ) Вот в Форме как раз и есть нечто подобное. Пришло событие от клавы или мышки - форма обработкала. Ну в самом деле, не драйвер же клавы этим занимается ) Всё же обработка клика мышки это работа потока формы... Зуб не дам, но я разочаруюсь совсему уже в Винде если узнаю что это не так.
Опять же, логика понятная, но низкоуровневая и ни разу не ООПшная Тут, в большинстве случаев, заморачиваться подобными вещами просто не нужно, такого рода вопросы обычно может порешать компилятор, а вам достаточно написать BeginInvoke, который, собственно, и делает именно то, что вы хотите, если судить по этому описанию. Про оконную процедуру-верно, она выполняется в потоке формы.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
по сути именно из всех ваших примеров я и получил свой вариант
В варианте от insite2012 было удобно сделано через наследование от вокрера. В моем варианте было сделано через классический поток и события. Вы же повырезали все из этих вариантов, что связано с ООП, и добавили лишний поток, что привело к избыточности и к тому, что логика и UI у вас не разделены, хотя вроде как именно этого вы хотите добиться
0
JustOneQuestion
0 / 0 / 0
Регистрация: 01.05.2015
Сообщений: 84
12.10.2015, 11:40  [ТС] #36
Еще раз повторю-шарп-это ООП язык. А вы пытаетесь навязать этому языку чуждую ему концепцию
Концепция которую предлагаю я не чуждая никому ). Разделение на потоки и межпоточное взаимодействие на уровне WaitHandle полностью вписывается в C# и его мсдн. Более того. Межпроцессовое взаимодействие тоже предусмотрено в C# и в мсдн соответсвенно через WaitHandle. https://msdn.microsoft.com/en-us/library/ksb7zs2x%28v=vs.110%29.aspx Named event wait handles can also be used to synchronize activities across application domains and processes, whereas monitors are local to an application domain.
Разделение UI и основного кода это не только разделение классов. Запуск паралельных процессов и их отключение по мере надобности вполне себе распространненная потребность. И это совсем не низкоуровневое программирование. И примеры задач и методы их реализации, которые я приводил, нельзя назвать низкоуровневыми. Мы не пишем драйвера, не идём в обход планровщика задач, не пишем код на асме вместо компилятора шарпа. Наоборот, я говорю на уровне уже готовых программ, езешников, возможно, коды которых написаны на разных языках и нет исходников ни возможности их изменить.НО! Но есть описание именных WaitHandle'ов с которыми эти программы могут работать. Я уже приводил пример, про музыкальный плеер. Часть кода для него лучше писать на С++. А другую часть на C#. И это удобнее будет и надежнее и рациональнее, чем всё писать на одном языке.
Пусть C# ООП язык. Но слишком много существует задач, которые на нём просто неудобно делать, и не меньше тех задач, для которых он идеален. А есть задачи которые совмещают в себе 2 класса подзадач, котоыре на шарпе удобно и котоыре не удобно делать. Вот тогда вполне разумно разбивать весь проект на подпроекты-модули, и подключать их время от времени в процессе работы. И event'ы тут скорее будут обузой нежели чем удачным решением проблемм. А вот WaitHandl'ы вполне себе подойдут.
Проблема только в том, что WinForms не имеет явной возможности реагировать на внешние WaitHandl'ы. (Точнее я так её и не нашёл). Создавать ещё один поток можно, да, согласен. Можно из этого потока через инвоки деркать контролы, да тоже согласен. Но что если вывод данных в форму из этого потока не самый тривиальный, типа как лабела текст поменять, а что-то более серьёзное, продолжительное, динамичное... Но при всём при этом, от основного потока по хорошему требуется только сказать форме ПроснисьИРаботай_(задание_35) и продолжить заниматься своими вещами. В случае event'ов вся эта муторная, продолжительная но не слишком КРИТИЧНАЯ работа ложится на главный поток. А поток формы балду пинает... Как то это не правильно. Тут нет ничего низко уровневого. Нет попирания законов ООП. Просто логичное и рациональное распеределение обязанностей и ресурсов ОС или железа. Поток можно рассматривать как нечто большее чем виртуально созданное перепрыгивание ОС с одной задачи на другую. Поток может быть и на разных ядра, процессроах, на разных устройствах и вобще между нашим компом и серверами альфацентавры , которые реализуют между собой оговоренный протокол взаимодействия. Ну не добиться этих межгалактических взаимодействий c незнакомыми программами через event'ы. А если и добиться.. то прейдётся платить альфацентавре за использование их вычислительных мощностей
Так вот WinForms имеют свою очередь, но я не знаю как ещё в неё встать, кроме как через BGWorker и его Progress событие. Он нужен только для этого. В нём можно спать, а можно работать в вечном лупе. Он может принимать внешние WaitHandl'ы и слать их. Он может работать с контролами формы в своём потоке через инвоки либо в потоке формы через событие ProgressChanged. Тоже самое с event'ами нельзя уже сделать. Можно правда сделать через PostMessage, но вечный луп в него не засунешь без DoEvents.
Вы же повырезали все из этих вариантов, что связано с ООП, и добавили лишний поток, что привело к избыточности и к тому, что логика и UI у вас не разделены, хотя вроде как именно этого вы хотите добиться
Вот тут я не понимаю, почему у меня не разделена логика и UI? Может из примера было не очеь ясно, но логика программы не в воркере а в MyMainF. А он в отдельном потоке. Классы я не стал разные делать - не в них суть. Но сделать то их не проблемма. Или только в этом заключается замечание о "неразделении"...?
0
EvilFromHell
944 / 843 / 267
Регистрация: 26.04.2012
Сообщений: 2,648
12.10.2015, 16:59 #37
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Разделение UI и основного кода это не только разделение классов.
В первую очередь - именно их.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
по хорошему требуется только сказать форме ПроснисьИРаботай_(задание_35) и продолжить заниматься своими вещами
Ну и чем по-вашему тут не подходит BeginInvoke? Он сразу возвращает управление потоку, в котором вызван, а форма уже сама разбирается, когда ей выполнять указанный код.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Классы я не стал разные делать - не в них суть. Но сделать то их не проблемма.
Эмм, а в чем вообще тогда смысл разделения UI и интерфейса? С точки зрения ООП смысл в том, чтобы каждый класс инкапсулировал в себе какой-то функционал, а остальное вокруг него с легкостью можно было заменить. Вот к примеру проектик, который я недавно писал на фрилансе. Надо было сделать бота для нескольких букмекерских контор. Не буду же я для каждого сайта писать свой UI, хотя работа с сайтами технически совершенно разная. Поэтому у меня там есть абстрактный класс, в котором объявлены сигнатуры методов, свойств и эвентов, которые интересуют UI. Дальше для каждого сайта наследуюсь от этого класса и реализую это все. UI же у меня в виде UserControlа, и принимает в конструктор объект, соответствующий абстрактному классу. Опрос сайтов происходит, естественно, в отдельном потоке, а все обработчики эвентов в UI сделаны через инвоки. В результате, если я захочу добавить новый сайт, мне вообще не надо трогать UI-достаточно унаследоваться от того абстрактного класса и переопределить нужные методы. В данной программе, понятное дело, ничего нигде не виснет. И как бы я то же самое реализовал без ООП?
0
JustOneQuestion
0 / 0 / 0
Регистрация: 01.05.2015
Сообщений: 84
13.10.2015, 16:19  [ТС] #38
Спасибо большое за ваши ответы и замечания. Очень полезны оказались для меня.
Ну и чем по-вашему тут не подходит BeginInvoke?
Вобще говоря подходит, это прямой аналог PostMessage. С той лишь разницей что просто PostMessage шлёт тока "сигнал" о том что нужно делать и параметры какие-то, а BeginInvoke шлёт ещё и код, код который будет исполнятся в порядке очереди в потоке формы, а тот поток что отправил этот код продолжит своё выполнение. Если честно я это понял только после вашего вопроса "чем тут не подходит...", когда задумался.. "а правда, и чем же?!..". Покопался поподробнее, почитал и вобщем оказалось, что это действительно то о чём я спрашивал - прямой аналог PostMessage.
Далее дело вкуса - можно писать код прям в делегат инвока в том потоке и классе из которого будет вызываться BeginInvoke, а можно (что мне ближе) в делегате указать только выполнение функции из класса формы, где её код полностью и будет.
Единственный момент, который не ясен с BeginInvoke, так это то, можно ли с помощью них работать не с двумя разными потоками одного приложения, а с двумя разными процессами двух разных приложений? Скажем запустить уже готовый екзешник программки, в которой только форма с её функционалом, и попытаться залезть в очередь этой формы из другого процесса. По идее это мягко говоря не безопасно и такие возможности должны быть зарезаны на корню... Казалось бы через WaitHandl'ы 'этой проблемы не было бы (код правда тогда тоже вроде не отправить... хотя кто знает... надо покопать).

Про разделение классов и ООП...
Конечно это важно, но это больше филосовский вопрос. На асме всё равно классов нет, а всё к нему сводится)
Главное как я уже говорил и как вы подтвердили это своим примером про ваш проект букмекеров - Существуют задачи для готорых C# и ООП в целом просто идеальны. И раз это можно на них сделать, более того если это на них уже сделано, и работает без проблемм, то зачем выдумывать альтернативу, если в ней нет необходимости. В мире и так полно задач котоыре уже поставлены, и которые очень нужно решить.
0
EvilFromHell
944 / 843 / 267
Регистрация: 26.04.2012
Сообщений: 2,648
13.10.2015, 18:12 #39
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
это прямой аналог PostMessage
Скорее даже не аналог, а обертка, которая позволяет не заморачиваться вещами типа запихивания нужных байтов в нужное место в lparam.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Единственный момент, который не ясен с BeginInvoke, так это то, можно ли с помощью них работать не с двумя разными потоками одного приложения, а с двумя разными процессами двух разных приложений?
Не, просто так влезть в чужое приложение и что-то там выполнить не выйдет
Again, the delegate information is not passed to the message queue. Internally there is a "stack" of callback objects where the delegate information is stored. The method called by the wndproc routine only needs to pop the topmost callback from the list to get the delegate information. It can then invoke it. I recommend that if you are still confused about how this happens you should open the source code in Reflector and review it. Look for Control.BeginInvoke and you'll see all the code. As for the conversion you will see that BeginInvoke calls PostMessage after it pushes the callback data onto the internal list.
То есть там по факту есть некий список с делегатами, о котором знает оконная процедура, куда BeginInvoke добавляет свой делегат, а потом вызывает PostMessage, который оконная процедура понимает как сигнал о том, что такой-то делегат из списка надо выполнить. При желании-есть .NetReflector, можно распотрошить системные DLLки и глянуть, что там и как реализовано.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Казалось бы через WaitHandl'ы 'этой проблемы не было бы (код правда тогда тоже вроде не отправить... хотя кто знает... надо покопать)
Такое в ряд ли возможно хоть где-то без лютых низкоуровневых извращений с залезанием в память другого процесса Другое дело, если второе приложение свое, то можно посылать ему что-то через сокеты/пайпы/еще что-нибудь, а потом уже пытаться выполнять. Но это все надо достаточно редко.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Конечно это важно, но это больше филосовский вопрос. На асме всё равно классов нет, а всё к нему сводится)
Ну можно и в двоичном коде писать программы, только дешевизной, понятностью, легкостью поддержки и скоростью разработки они явно отличаться не будут
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Существуют задачи для готорых C# и ООП в целом просто идеальны
ООП и язык C#-достаточно универсальные инструменты, я с трудом представляю задачу достаточно большого объема, для которой бы ООП не подошло. Другой вопрос в том, что с ООП связаны некоторые накладные расходы в плане производительности,а язык C# завязан на .NET, это, собственно, и ограничивает их область применения. Ну и что-то низкоуровневое на нем писать тяжело, почти все навороты языка нельзя будет использовать.

Добавлено через 6 минут
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Далее дело вкуса - можно писать код прям в делегат инвока в том потоке и классе из которого будет вызываться BeginInvoke, а можно (что мне ближе) в делегате указать только выполнение функции из класса формы, где её код полностью и будет.
Ну так-этот вопрос уже решается при помощи eventoв. Подписываетесь на эвенты, а в обработчике оборачиваете код в Invoke:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
       
SD.SomethingWrong += OnSomethingWrong;
 private void OnSomethingWrong(Exception e)
        {
            this.BeginInvoke(new Action(() => {
                ErrorLabel.Text = e.Message;
                if (e.Message == "Нет связи с сервером") {
                    Timer t = new Timer();
                    t.Tick += (s,ee) => { ErrorLabel.Text = ""; (s as Timer).Stop(); (s as Timer).Dispose(); };
                    t.Interval = 20000;
                    t.Start();
                    return; }
                button1.PerformClick();
            })); 
        }
В данном коде-обработчик эвента, вызываемого в другом потоке.
0
JustOneQuestion
0 / 0 / 0
Регистрация: 01.05.2015
Сообщений: 84
13.10.2015, 19:39  [ТС] #40
ООП и язык C#-достаточно универсальные инструменты, я с трудом представляю задачу достаточно большого объема, для которой бы ООП не подошло.
Вот не то что-бы ООП не подошло, но C# в текущем варианте (родные библиотеки, без сторонних самоделок) очень плохо умеет работать с устройствами, тем более на низком уровне (я не про драйвера). А задачи такие: несколько (порядка 10ка) различных устройств USB, video, com, audio устройства собирают данные от некоторого процесса а так же управляют чем-то (моторами какимто или внешними генераторами напряжения), ацп и проче проче прочее. И всё полученные данные должны отправляться на комп, там обрабатываться довольно ресурсоёмкими алгоритмами, отображаться в виде графиков, и прочих логов на компе, плюс необходимо всем этим набором устройств управлять с компа, не с конфиг файлов или консоли а с помощью виндовых форм. Винда нужна тупо из-за того что слишком много софта под неё сделано + пользователи её не боятся. Короче надо ВИНДУ (. Вот всё эту свору меню писать даже на С++ довольно трудоёмко и не очень удобно, по сравнению с C#. А вот часть которая отвечает за работу с железом уже неудобно писать на C#. Вот собственно и пример.
Выхода два: забить на удобство и всё делать на С++, или же часть на C# а часть на С++. Ну с первым вариантом я уже намучался в своё время... вот собственно и думаю как бы так сделать, чтобы мой пример с ком-портом после разрастания не превратилась в адского монстра...Я его делал только чтобы отдельный модуль протестить когда спаял. Ща пытаюсь придумать что-то вроде универсального интерфейса между отдельными кусками программы, который бы для всех языков был бы доступен. В этом ключе почемуто хочется чтобы програмные модули (назову так разные подпрограммы для разных устройст, котоыре будут запускаться независимо и взаимодействовать между собой через ... вот тут я тоже ещё не выбрал через что.) работали с одним каким-то общим "интерфесом". Всмысле способ обмена данными и событиями друг с другом был у всех одинаков,... и у окон тоже. А если инвоки не могут между разными процессами работать, то наверно они тут не подойдут. Конечно можно каждому устройству свою пару делать программа-окно.... Но пока не определился.
0
EvilFromHell
944 / 843 / 267
Регистрация: 26.04.2012
Сообщений: 2,648
13.10.2015, 21:00 #41
Ммм, вот тут уже тяжело будет что-то квалифицированно советовать, ибо с подобными вещами я не работал. Все это физически подключено к компу или передается по сети? Если все на одном компе, то можно все написать в одной программе. Если же не обязательно-то для каждого различного устройства небольшая программка(пофигу на чем), которая передает данные на некий сервер, принимающий подключения. Сервер можно реализовать в виде консольной программки на C++ или вообще чистом С, ибо там, как я понял, ресурсоемкий алгоритм. А на шарпе написать оболочку для этой консольной программы, консольный ввод-вывод элементарано перенаправляется. Во всяком случае это первое, что приходит в голову, возможно кто-то с большим опытом в данном деле предложит что-то рациональнее.
0
JustOneQuestion
0 / 0 / 0
Регистрация: 01.05.2015
Сообщений: 84
14.10.2015, 08:22  [ТС] #42
А на шарпе написать оболочку для этой консольной программы, консольный ввод-вывод элементарано перенаправляется.
А что по этому поводу посоветуете? Есть просто одна консольная програмка, которую точно надо будет использовать, но она на Qt написана, в силу того что библиотеки для работы с одним из устройств написаны тока для Qt. А это для меня всё ещё дремучий лес. С моими платами то проблем не будет, они не сложные и я использую стандартные дрова от винды. А вот с этой точно будут проблемы. Я подозреваю должны быть способы и не один как из консольного приложения выдрать данные в другой процесс и засовывать команды в консоль обратно.
0
EvilFromHell
944 / 843 / 267
Регистрация: 26.04.2012
Сообщений: 2,648
14.10.2015, 19:48 #43
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
А что по этому поводу посоветуете? Есть просто одна консольная програмка, которую точно надо будет использовать, но она на Qt написана, в силу того что библиотеки для работы с одним из устройств написаны тока для Qt. А это для меня всё ещё дремучий лес. С моими платами то проблем не будет, они не сложные и я использую стандартные дрова от винды. А вот с этой точно будут проблемы. Я подозреваю должны быть способы и не один как из консольного приложения выдрать данные в другой процесс и засовывать команды в консоль обратно.
Консольным приложением можно очень просто управлять, перенаправив потоки ввода-вывода. Все это реализовано в классе Process. Это позволяет представить консольный ввод/вывод того второго приложения как 2 потока, в которые вы можете что хотите писать или считывать. Пример, и еще пример.
0
JustOneQuestion
0 / 0 / 0
Регистрация: 01.05.2015
Сообщений: 84
16.10.2015, 10:43  [ТС] #44
Спасибо. буду разбираться.
Вобщем-то все вопросы которые относились к заголовку темы разобраны и весьма подробно. Остальное позже вынесу в другую тему. Пока есть о чём подумать.
Спасибо всем.
0
16.10.2015, 10:43
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.10.2015, 10:43
Привет! Вот еще темы с ответами:

Как разделить события цифр на цифровой клавиатуре (NumLoсk) и события цифр расположенных над символами? - C#
Помогите пожалуйста! Как разделить события цифр на цифровой клавиатуры (NumLok) и события цифор расположенных над символами. Дело в...

Как сделать ожидание полной загрузки страницы в webbrowser? - C#
Мне необходимо достать код страницы html из webbrowser в c#. С этим проблем не возникает. Если же страница после открытия еще догружает...

Перенос массива из класса события в другой класс события - C#
есть вот такой код: private void button_follow_Click(object sender, EventArgs e) { if...

Вызов события из другого события - C#
Есть событие button4_Click, надо из него вызвать button3_Click. Как сделать?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
44
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru