|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
Задача вытекает из рассуждений в этой теме: Хочу понять логику "уведомлений в трей". AntonariyДобавлять в коллекцию новые сообщения и брать из нее первое сообщение (удаляя) и не показывать следующее, пока юзер не кликнет тултип. Т.е. произошло событие - добавили сообщение в "конец очереди" если в очереди есть сообщение - взяли первое - показали в трей как Notification пользователь закрыл Notification, или оно вышло по таймауту, или приложение его удалило -удалили сообщение пользователь щелкнул по Notification - выполнили команду в соответствии с типом и параметрами тек. сообщения -удалили сообщение. Удалив сообщение, смотрим не остался ли кто в очереди, если да, то берем первое и т.д. Ну, модификации - показать сообщение без очереди если у него какой-то приоритет, выкинуть его (не обязательно первое), если оно уже не актуально и т.д. Я с коллекциями по жизни не очень то сталкивался. Даже не знаю. Мне приходит в голову массив плавающей длины, с данным паровозом вроде как привык работать: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42.
Ну, типа набросал алгоритм. Сразу вопрос. Код: vbnet 1.
А как сделать ReDim чтоб НИ ОДНОГО элемента не осталось. Без "технического" нулевого элемента массива. Сойдет так? Или все таки заморачиваться с коллекцией? Еще вижу варианты: скрытый ListView, таблица в БД (хотя это уже думаю излишки). ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 05:36 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
Заморочки как раз с массивом, с коллекцией их нет. Код: vbnet 1. 2. 3. 4. 5. 6.
Но в коллекции нельзя хранить переменные пользовательского типа, только примитивные или объекты. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 08:31 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
Antonariy, Я не уверен что смогу обойтись без пользовательского типа при описании сообщения. Чем тогда мой вариант с массивом плох? и где там могут быть заморочки? ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 09:36 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
>Дмитрий77, сегодня, 09:36 [14426369] >Чем тогда мой вариант с массивом плох ... Рассмотрите вариант "кольцевого" массива. Два указателя (индекса) - на чтение и на запись. Запись - по указателю и его увеличение с проверкой на границу массива Чтение - проверка на равенство с указателем чтения, если нет, читаем и увеличиваем с проверкой на границу массива Что делать с переполнением, решайте сами - затирать последний или пропускать текущий С уважением, Владимир. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 09:48 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
Дмитрий77Я не уверен что смогу обойтись без пользовательского типа при описании сообщения.Вариант первый - сериализация в стринг. Вариант второй - создание своего класса "Сообщение и информация о нём". Дмитрий77Чем тогда мой вариант с массивом плох? и где там могут быть заморочки?А чем он хорош? ну кроме того, что это ЛИЧНО ВЫ не хотите изучить работу с коллекцией (что, кстати, совсем несложно). Дмитрий77А как сделать ReDim чтоб НИ ОДНОГО элемента не осталось. Без "технического" нулевого элемента массива. Erase Однако НАСТОЯТЕЛЬНО рекомендую этого не делать - определение, в каком из трёх состояний находится массив, будет затруднительным, и если определить состояние "удалён, не определён" нетрудно, то различить варианты "определён, но не инициализирован" и "определён и инициализирован", не задействуя обработчик ошибок, трудновато. Держите в массиве нулевой элемент, но не используйте его для хранения данных. Так снимутся все вопросы с зачисткой. Впрочем, нулевой элемент не будет мотаться зря - как раз его удобно использовать в качестве промежуточного буфера при обмене местами двух элементов массива (сортировка, сжатие). ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 09:58 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
Дмитрий77Antonariy, Я не уверен что смогу обойтись без пользовательского типа при описании сообщения.И не обязательно. Можно свойству класса присвоить пользовательский тип. Дмитрий77Чем тогда мой вариант с массивом плох?Исключительно количеством кода. Дмитрий77и где там могут быть заморочки?У тебя их не будет. Они могут быть у того, кто будет поддерживать этот код после тебя. 4 строчки с коллекцией понятней, чем полтора десятка с массивом, согласись. ВМоисеевРассмотрите вариант "кольцевого" массива.А это еще более заморочено. И не нужно. Коллекция по сути является очередью и не требует никаких экстра плясок с бубном в этом смысле. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 12:00 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
AntonariyКоллекция по сути является очередью Эммм... а нет ли ссылочки на описание НАЧИНКИ коллекции? как она организована, внутренняя её механика? По её поведению у меня всегда было подозрение, что унутре это всего лишь динамический массив указателей на элементы... но нигде не смог найти ответы на некоторые достаточно важные вопросы - например, может ли добавление/удаление элементов поменять взаимное расположение ранее существовавших элементов при обработке в итераторе For Each? гарантировано ли сохранение индекса элемента, если все изменения выполняются на элементах с бОльшими индексами? и т.п... ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 12:06 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
AkinaAntonariyКоллекция по сути является очередью Эммм... а нет ли ссылочки на описание НАЧИНКИ коллекции? как она организована, внутренняя её механика?На bbs.vbstreets.ru спроси, тамошний модер крутой спец по потрохам VB. AkinaПо её поведению у меня всегда было подозрение, что унутре это всего лишь динамический массив указателей на элементы... Не исключено. Я же имел ввиду поведение с точки зрения сферической очереди: добавляешь в конец, удаляешь из начала, индексы элементов сдвигаются. Akinaможет ли добавление/удаление элементов поменять взаимное расположение ранее существовавших элементов при обработке в итераторе For Each?Если ты добавляешь/удаляешь внутри For Each, то очередная итерация приведет к ошибке "коллекция была изменена". Присвоить элементу коллекции новое значение нельзя. Можно изменить само значение. Akinaгарантировано ли сохранение индекса элемента, если все изменения выполняются на элементах с бОльшими индексами? и т.п...Да. Обход коллекции с ее изменением нужно начинать с конца. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 12:22 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
вообще то коллекции не сортированы. так что я бы не стал забиваться на сохранение индекса (при удалении внутренних элементов). но на planetsourcecode были примеры сортировок для коллекций на основе синтетических ключей. если нужны возможности быстрой и гарантированной сортировки , то лучше ищите готовые классы по работе с массивами (по ключевым словам: пузырьковая сортировка и тп) ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 12:31 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
Konst_Oneвообще то коллекции не сортированы. так что я бы не стал забиваться на сохранение индексаТо есть если я удаляю из середины, то элементы в начале могут перемешаться или вообще ускакать в конец? Не говори ерунды. Нет ни одной причины, по которой это может произойти. Я всегда полагался на неизменность индексов и ни разу они меня не подвели. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 12:36 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
нет, конечно никуда они не перескочат, я про другое: если нужна сквозная непрерывная нумерация (без разрывов), то индекс коллекции для этих целей не подходит ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 12:38 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
Почему? Индекс сквозной и непрерывный. Другое дело, что он не сохраняется за элементом, но это естественно и очевидно. Порядок элементов не меняется, это самое главное. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 12:42 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
согласен ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 12:53 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
"Никакое количество экспериментов не может служить доказательством теории." AntonariyТо есть если я удаляю из середины, то элементы в начале могут перемешаться или вообще ускакать в конец? Не говори ерунды. Нет ни одной причины, по которой это может произойти. Я всегда полагался на неизменность индексов и ни разу они меня не подвели. AntonariyПорядок элементов не меняется, это самое главное. Вот именно об этом моменте я и говорю. Гарантируется ли неизменность порядка элементов? Меня интересует - есть ли гарантия, что такое поведение абсолютно? или наоборот - что теоретически есть условия, при которых эта регулярно наблюдаемая зависимость поломается? А на то, чтобы не менять коллекцию в итераторе, у меня мозгов вполне достаточно... ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 13:09 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
"Никакое количество экспериментов не может быть гарантией" Нет ничего абсолютного, кроме самого абсолюта. Кто-то вломится в память процесса и натопчет там, или ты сам решишь поиграться с памятью и налажаешь — вот тебе и теоретические условия. Означает ли это, что нужно защищать процесс от несанкционированного доступа? Не доводи до абсурда. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 13:42 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
То, что вмешательство нештатными средствами может изменить заложенные алгоритмы работы - очевидно. Однако выяснение точного штатного алгоритма работы для любых штатных операций и любых входных параметров в допустимом диапазоне я лично абсурдом не считаю... все, в том числе и я, на текущий момент полагают, что добавление либо удаление либо изменение элемента с номером индекса "зю" не вызывает изменения индексов элементов, номера которых менее этого "зю". Однако нет ни доказательства, что так будет всегда, ни условий, когда будет иначе. Между "истина" и "пока вроде истина" - есть некоторая разница. ИМХО. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 14:16 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
Ок. Не можешь без гарантий — не пользуйся. Не доверяешь никакому опыту — не пользуйся. Мне все равно. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 14:25 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
AkinaПо её поведению у меня всегда было подозрение, что унутре это всего лишь динамический массив указателей на элементы... но нигде не смог найти ответы на некоторые достаточно важные вопросы - например, может ли добавление/удаление элементов поменять взаимное расположение ранее существовавших элементов при обработке в итераторе For Each? гарантировано ли сохранение индекса элемента, если все изменения выполняются на элементах с бОльшими индексами? и т.п...На внутреннюю организацию ограничений не накладывается (и по гамбургскому счёту, даже программист, её пишущий, может не знать всех деталей реализации, так как может пользоваться библиотечными классами вроде ассоциативных массивов (скажем, std::map), которые могут меняться от библиотеки к библиотеке и от версии к версии). Для поддержки For Each коллекция должна поддерживать интерфейс IEnumVariant . Но описание этого интерфейса не накладывает существенных ограничений на реализацию метода IEnumVariant::Next() , не понятно из описания, влияет ли на enumeration sequence вставка/удаление элемента. Более того, в описании метода Reset() есть такие слова:IEnumVARIANT::Reset methodThere is no guarantee that exactly the same set of variants will be enumerated the second time as was enumerated the first time. Although an exact duplicate is desirable, the outcome depends on the collection being enumerated. You may find that it is impractical for some collections to maintain this condition (for example, an enumeration of the files in a directory).Из чего напрашивается вывод, что Next() может вести себя как пожелает программист, реализующий коллекцию. В качестве примера реализации Microsoft в описании IEnumVariant ссылается на пример Lines Sample . Не вдавался в подробности, но с виду safe array VARIANT-ов (что обеспечивает скорость доступа O(1) к элементу по индексу). Возможно, похожая реализация и у VBA.Collection. А, может, и нет. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 16:58 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
AntonariyНо в коллекции нельзя хранить переменные пользовательского типа, только примитивные или объекты.В Variant можно засунуть пользовательский тип, если он описан в библиотеке типов (и имеет GUID). ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 17:04 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
БенедиктAntonariyНо в коллекции нельзя хранить переменные пользовательского типа, только примитивные или объекты.В Variant можно засунуть пользовательский тип, если он описан в библиотеке типов (и имеет GUID).В справке по VB таких тонкостей нет :) ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 17:12 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
Про коллекции я честно перечитал 3 страницы книги (Семейства там это называется), но ничего большего чем написал Antonariy во втором посте из книги не вычитал. Сдается мне, прочитав все рассуждения, что идея с массивом() + Redim [Preserv] таки проще и понятней будет. По крайней мере я логически понимаю что я делаю и не доверяю свою логику автоматике начинка которой вызывает такие дебаты. Тем более эта технология с массивами и вложенными пользовательскими типами у меня "отработана". AkinaДмитрий77А как сделать ReDim чтоб НИ ОДНОГО элемента не осталось. Без "технического" нулевого элемента массива. Erase Однако НАСТОЯТЕЛЬНО рекомендую этого не делать - определение, в каком из трёх состояний находится массив, будет затруднительным, и если определить состояние "удалён, не определён" нетрудно, то различить варианты "определён, но не инициализирован" и "определён и инициализирован", не задействуя обработчик ошибок, трудновато. Держите в массиве нулевой элемент, но не используйте его для хранения данных. Так снимутся все вопросы с зачисткой. Впрочем, нулевой элемент не будет мотаться зря - как раз его удобно использовать в качестве промежуточного буфера при обмене местами двух элементов массива (сортировка, сжатие). Ну, так я и делаю. Всегда могу сделать UBound, и знаю что следующий элемент будет UBound+1, а если UBound=0, то значит массив "пустой". На абсолютно пустой массив UBound ведь ругается. Да, кстати. Код: vbnet 1. 2. 3. 4. 5. 6. 7.
app_messages.m_MyMessages(i)=app_messages.m_MyMessages(i+1) (для пользовательского типа) не подведет? Или правильнее: Код: vbnet 1. 2. 3.
Вот это наверно излишки (на другой код глядючи) Код: vbnet 1. 2. 3. 4. 5.
Достаточно думаю Код: vbnet 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 17:43 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
AntonariyВ справке по VB таких тонкостей нет :)Ну... просто, пытаясь передать UDT в Public-методы, принимающие Variant, ещё на этапе компиляции наталкиваешься на ошибку "Only user-defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions" (что-там говорится в справке, уже не помню), и начинаешь думать, как переводить это с иезуитского на человеческий. При переводе выходит, что если UDT объявить в классе с Public instancing-ом, то, вроде, должно получиться. То есть объявляем Public Type в Public-классе в проекте типа, например, ActiveX DLL, и ссылаемся на этот проект в своём. Либо другой вариант, пишем на ODL/IDL свою библиотеку типов, компилируем, ссылаемся. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 17:53 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
Кстати говоря Akina различить варианты "определён, но не инициализирован" и "определён и инициализирован", не задействуя обработчик ошибок, трудновато Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
Этого тоже не найдешь в документациях, но работает как часы. Впрочем, как и коллекция. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 17:59 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
Бенедикт"Only user-defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions"Я уже забыл этот текст, а теперь увидел и вспомнил, что типы, объявленные в публичных классах вполне себе добавлялись. Просто в standart exe нельзя сделать публичный класс. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 18:03 |
|
А как грамотно организовать "очередь сообщений"
|
|||
---|---|---|---|
#18+
>Antonariy, сегодня, 12:00 [14427351] >А это еще более заморочено. И не нужно. Может быть Вы и правы, но опыт показывает эффективность подобной конструкции (извините что на C#) //========================================================================================= static int изССД = 0; //-- индекс записи static int ичССД = 0; //-- индекс чтения const int рцмССД = 1024; //-- размер циклического массива СообщенияСерверуДанных в сообщениях static byte[][] СообщенияСерверуДанных = new byte[рцмССД][]; //-- Читаем сообщение из циклического массива СообщенияСерверуДанных //-- выход: byte[] - байтовая строка сообщения //================================================= byte[] fЧтениеСообщенияСерверуДанных_lock() { byte[] xbb; lock(СообщенияСерверуДанных) {xbb=fЧтениеСообщенияСерверуДанных();} return xbb; } byte[] fЧтениеСообщенияСерверуДанных() { byte[] xbb = null; if (изССД != ичССД) { //-- Есть не обработанный запрос xbb = СообщенияСерверуДанных[ичССД]; СообщенияСерверуДанных[ичССД] = null; ичССД= (++ичССД) % рцмССД; } return xbb; } void fЗаписьСообщенияСерверуДанных_lock(byte[] bbb) { lock (СообщенияСерверуДанных) { fЗаписьСообщенияСерверуДанных(bbb); } } void fЗаписьСообщенияСерверуДанных(byte[] bbb) { СообщенияСерверуДанных[изССД] = bbb; //-- Запись тела сообщения изССД = (++изССД) % рцмССД; if (изССД == ичССД) ичССД = (++ичССД) % рцмССД; //-- При необходимости изменим индекс чтения } Использую для случая, когда несколько пишут, один читает. Небольшое изменение - и несколько пишут, несколько читают. Могу писать неограниченное количество сообщений (реально остаются последние). Схема допускает оптимизацию, если известна мах. длина обрабатываемых сообщений. С уважением, Владимир. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.06.2013, 18:21 |
|
|
start [/forum/topic.php?fid=60&msg=38296029&tid=2156913]: |
0ms |
get settings: |
11ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
48ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
53ms |
get tp. blocked users: |
1ms |
others: | 296ms |
total: | 443ms |
0 / 0 |