Гость
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / А как грамотно организовать "очередь сообщений" / 25 сообщений из 26, страница 1 из 2
13.06.2013, 05:36
    #38295575
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
Задача вытекает из рассуждений в этой теме:
Хочу понять логику "уведомлений в трей".
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.
Private Type MyMessage
   m_type as MessageType 'enum?
   m_parameter as string
   ...
End Type

Private Type AppMessages
  m_MyMessages() As MyMessage
End Type

Public app_messages As AppMessages

'Инициализация

ReDim app_messages.m_MyMessages(0 To 0) 'очистка-0-й элемент не используется

'Добавление
    Dim new_message As MyMessage
    with new_message
      .m_type =...
      ...
    endif
     ReDim Preserve app_messages.m_MyMessages(0 To UBound(app_messages.m_MyMessages)) + 1)
     app_messages.m_MyMessages(UBound(app_messages.m_MyMessages)) =new_message
    'сюда же сразу вызов в трей если нет текущего активного сообщения
    If UBound(app_messages.m_MyMessages)=2 then 'кроме добавленного сообщения ничего нет 
        'показать в трей app_messages.m_MyMessages(1)
    end if

'Удаление (пусть первого элемента)
   if UBound(app_messages.m_MyMessages)>2 then '0-не используется, 1-удаляемое, 2-следующее и т.д.
     'сдвиг на единицу к началу
     for i=1 to UBound(app_messages.m_MyMessages)-1
       app_messages.m_MyMessages(i)=app_messages.m_MyMessages(i+1)
     next
   endif
   'удаляем последнее (сдвинуто вперед) 
   ReDim Preserve app_messages.m_MyMessages(0 To UBound(app_messages.m_MyMessages)) - 1)
    'сюда же сразу вызов в трей если чего-то осталось
    If UBound(app_messages.m_MyMessages)>1 then 'есть сообщение хотя бы одно 
       'показать в трей app_messages.m_MyMessages(1)
    end if



Ну, типа набросал алгоритм.

Сразу вопрос.
Код: vbnet
1.
ReDim app_messages.m_MyMessages(0 To 0) 'очистка-0-й элемент не используется


А как сделать ReDim чтоб НИ ОДНОГО элемента не осталось.
Без "технического" нулевого элемента массива.

Сойдет так?
Или все таки заморачиваться с коллекцией?

Еще вижу варианты: скрытый ListView, таблица в БД (хотя это уже думаю излишки).
...
Рейтинг: 0 / 0
13.06.2013, 08:31
    #38295624
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
Заморочки как раз с массивом, с коллекцией их нет.

Код: vbnet
1.
2.
3.
4.
5.
6.
Dim col As New Collection

col.Add msg 'добавляется в конец очереди
Set msg = col(1) 'первый элемент очереди
col.Remove 1 'удаление первого элемента, остальные автоматически сдвигаются
Set col = New Collection 'обнуление

Но в коллекции нельзя хранить переменные пользовательского типа, только примитивные или объекты.
...
Рейтинг: 0 / 0
13.06.2013, 09:36
    #38295675
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
Antonariy,

Я не уверен что смогу обойтись без пользовательского типа при описании сообщения.
Чем тогда мой вариант с массивом плох? и где там могут быть заморочки?
...
Рейтинг: 0 / 0
13.06.2013, 09:48
    #38295696
ВМоисеев
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
>Дмитрий77, сегодня, 09:36 [14426369]
>Чем тогда мой вариант с массивом плох ...

Рассмотрите вариант "кольцевого" массива. Два указателя (индекса) - на чтение и на запись.
Запись - по указателю и его увеличение с проверкой на границу массива
Чтение - проверка на равенство с указателем чтения, если нет, читаем и увеличиваем с проверкой на границу массива
Что делать с переполнением, решайте сами - затирать последний или пропускать текущий

С уважением, Владимир.
...
Рейтинг: 0 / 0
13.06.2013, 09:58
    #38295711
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
Дмитрий77Я не уверен что смогу обойтись без пользовательского типа при описании сообщения.Вариант первый - сериализация в стринг.
Вариант второй - создание своего класса "Сообщение и информация о нём".
Дмитрий77Чем тогда мой вариант с массивом плох? и где там могут быть заморочки?А чем он хорош? ну кроме того, что это ЛИЧНО ВЫ не хотите изучить работу с коллекцией (что, кстати, совсем несложно).

Дмитрий77А как сделать ReDim чтоб НИ ОДНОГО элемента не осталось.
Без "технического" нулевого элемента массива.
Erase
Однако НАСТОЯТЕЛЬНО рекомендую этого не делать - определение, в каком из трёх состояний находится массив, будет затруднительным, и если определить состояние "удалён, не определён" нетрудно, то различить варианты "определён, но не инициализирован" и "определён и инициализирован", не задействуя обработчик ошибок, трудновато.
Держите в массиве нулевой элемент, но не используйте его для хранения данных. Так снимутся все вопросы с зачисткой. Впрочем, нулевой элемент не будет мотаться зря - как раз его удобно использовать в качестве промежуточного буфера при обмене местами двух элементов массива (сортировка, сжатие).
...
Рейтинг: 0 / 0
13.06.2013, 12:00
    #38295945
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
Дмитрий77Antonariy,

Я не уверен что смогу обойтись без пользовательского типа при описании сообщения.И не обязательно. Можно свойству класса присвоить пользовательский тип.
Дмитрий77Чем тогда мой вариант с массивом плох?Исключительно количеством кода.
Дмитрий77и где там могут быть заморочки?У тебя их не будет. Они могут быть у того, кто будет поддерживать этот код после тебя. 4 строчки с коллекцией понятней, чем полтора десятка с массивом, согласись.
ВМоисеевРассмотрите вариант "кольцевого" массива.А это еще более заморочено. И не нужно.

Коллекция по сути является очередью и не требует никаких экстра плясок с бубном в этом смысле.
...
Рейтинг: 0 / 0
13.06.2013, 12:06
    #38295961
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
AntonariyКоллекция по сути является очередью
Эммм... а нет ли ссылочки на описание НАЧИНКИ коллекции? как она организована, внутренняя её механика?

По её поведению у меня всегда было подозрение, что унутре это всего лишь динамический массив указателей на элементы... но нигде не смог найти ответы на некоторые достаточно важные вопросы - например, может ли добавление/удаление элементов поменять взаимное расположение ранее существовавших элементов при обработке в итераторе For Each? гарантировано ли сохранение индекса элемента, если все изменения выполняются на элементах с бОльшими индексами? и т.п...
...
Рейтинг: 0 / 0
13.06.2013, 12:22
    #38296008
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
AkinaAntonariyКоллекция по сути является очередью
Эммм... а нет ли ссылочки на описание НАЧИНКИ коллекции? как она организована, внутренняя её механика?На bbs.vbstreets.ru спроси, тамошний модер крутой спец по потрохам VB.

AkinaПо её поведению у меня всегда было подозрение, что унутре это всего лишь динамический массив указателей на элементы... Не исключено. Я же имел ввиду поведение с точки зрения сферической очереди: добавляешь в конец, удаляешь из начала, индексы элементов сдвигаются.

Akinaможет ли добавление/удаление элементов поменять взаимное расположение ранее существовавших элементов при обработке в итераторе For Each?Если ты добавляешь/удаляешь внутри For Each, то очередная итерация приведет к ошибке "коллекция была изменена".
Присвоить элементу коллекции новое значение нельзя. Можно изменить само значение.

Akinaгарантировано ли сохранение индекса элемента, если все изменения выполняются на элементах с бОльшими индексами? и т.п...Да. Обход коллекции с ее изменением нужно начинать с конца.
...
Рейтинг: 0 / 0
13.06.2013, 12:31
    #38296029
Konst_One
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
вообще то коллекции не сортированы. так что я бы не стал забиваться на сохранение индекса (при удалении внутренних элементов). но на planetsourcecode были примеры сортировок для коллекций на основе синтетических ключей. если нужны возможности быстрой и гарантированной сортировки , то лучше ищите готовые классы по работе с массивами (по ключевым словам: пузырьковая сортировка и тп)
...
Рейтинг: 0 / 0
13.06.2013, 12:36
    #38296034
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
Konst_Oneвообще то коллекции не сортированы. так что я бы не стал забиваться на сохранение индексаТо есть если я удаляю из середины, то элементы в начале могут перемешаться или вообще ускакать в конец? Не говори ерунды. Нет ни одной причины, по которой это может произойти. Я всегда полагался на неизменность индексов и ни разу они меня не подвели.
...
Рейтинг: 0 / 0
13.06.2013, 12:38
    #38296043
Konst_One
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
нет, конечно никуда они не перескочат, я про другое: если нужна сквозная непрерывная нумерация (без разрывов), то индекс коллекции для этих целей не подходит
...
Рейтинг: 0 / 0
13.06.2013, 12:42
    #38296051
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
Почему? Индекс сквозной и непрерывный. Другое дело, что он не сохраняется за элементом, но это естественно и очевидно.
Порядок элементов не меняется, это самое главное.
...
Рейтинг: 0 / 0
13.06.2013, 12:53
    #38296073
Konst_One
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
согласен
...
Рейтинг: 0 / 0
13.06.2013, 13:09
    #38296113
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
"Никакое количество экспериментов не может служить доказательством теории."
AntonariyТо есть если я удаляю из середины, то элементы в начале могут перемешаться или вообще ускакать в конец? Не говори ерунды. Нет ни одной причины, по которой это может произойти. Я всегда полагался на неизменность индексов и ни разу они меня не подвели.
AntonariyПорядок элементов не меняется, это самое главное.
Вот именно об этом моменте я и говорю. Гарантируется ли неизменность порядка элементов? Меня интересует - есть ли гарантия, что такое поведение абсолютно? или наоборот - что теоретически есть условия, при которых эта регулярно наблюдаемая зависимость поломается?
А на то, чтобы не менять коллекцию в итераторе, у меня мозгов вполне достаточно...
...
Рейтинг: 0 / 0
13.06.2013, 13:42
    #38296176
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
"Никакое количество экспериментов не может быть гарантией"

Нет ничего абсолютного, кроме самого абсолюта. Кто-то вломится в память процесса и натопчет там, или ты сам решишь поиграться с памятью и налажаешь — вот тебе и теоретические условия. Означает ли это, что нужно защищать процесс от несанкционированного доступа?

Не доводи до абсурда.
...
Рейтинг: 0 / 0
13.06.2013, 14:16
    #38296237
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
То, что вмешательство нештатными средствами может изменить заложенные алгоритмы работы - очевидно.
Однако выяснение точного штатного алгоритма работы для любых штатных операций и любых входных параметров в допустимом диапазоне я лично абсурдом не считаю... все, в том числе и я, на текущий момент полагают, что добавление либо удаление либо изменение элемента с номером индекса "зю" не вызывает изменения индексов элементов, номера которых менее этого "зю". Однако нет ни доказательства, что так будет всегда, ни условий, когда будет иначе. Между "истина" и "пока вроде истина" - есть некоторая разница. ИМХО.
...
Рейтинг: 0 / 0
13.06.2013, 14:25
    #38296258
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
Ок. Не можешь без гарантий — не пользуйся. Не доверяешь никакому опыту — не пользуйся.

Мне все равно.
...
Рейтинг: 0 / 0
13.06.2013, 16:58
    #38296561
Бенедикт
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
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. А, может, и нет.
...
Рейтинг: 0 / 0
13.06.2013, 17:04
    #38296569
Бенедикт
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
AntonariyНо в коллекции нельзя хранить переменные пользовательского типа, только примитивные или объекты.В Variant можно засунуть пользовательский тип, если он описан в библиотеке типов (и имеет GUID).
...
Рейтинг: 0 / 0
13.06.2013, 17:12
    #38296581
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
БенедиктAntonariyНо в коллекции нельзя хранить переменные пользовательского типа, только примитивные или объекты.В Variant можно засунуть пользовательский тип, если он описан в библиотеке типов (и имеет GUID).В справке по VB таких тонкостей нет :)
...
Рейтинг: 0 / 0
13.06.2013, 17:43
    #38296643
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
Про коллекции я честно перечитал 3 страницы книги (Семейства там это называется), но ничего большего чем написал Antonariy во втором посте из книги не вычитал.

Сдается мне, прочитав все рассуждения, что идея с массивом() + Redim [Preserv] таки проще и понятней будет.
По крайней мере я логически понимаю что я делаю и не доверяю свою логику автоматике начинка которой вызывает такие дебаты.
Тем более эта технология с массивами и вложенными пользовательскими типами у меня "отработана".

AkinaДмитрий77А как сделать ReDim чтоб НИ ОДНОГО элемента не осталось.
Без "технического" нулевого элемента массива.
Erase
Однако НАСТОЯТЕЛЬНО рекомендую этого не делать - определение, в каком из трёх состояний находится массив, будет затруднительным, и если определить состояние "удалён, не определён" нетрудно, то различить варианты "определён, но не инициализирован" и "определён и инициализирован", не задействуя обработчик ошибок, трудновато.
Держите в массиве нулевой элемент, но не используйте его для хранения данных. Так снимутся все вопросы с зачисткой. Впрочем, нулевой элемент не будет мотаться зря - как раз его удобно использовать в качестве промежуточного буфера при обмене местами двух элементов массива (сортировка, сжатие).
Ну, так я и делаю. Всегда могу сделать UBound, и знаю что следующий элемент будет UBound+1, а если UBound=0, то значит массив "пустой". На абсолютно пустой массив UBound ведь ругается.

Да, кстати.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
'Удаление (пусть первого элемента)
   if UBound(app_messages.m_MyMessages)>1 then '0-не используется, 1-удаляемое, 2-следующее и т.д.
     'сдвиг на единицу к началу
     for i=1 to UBound(app_messages.m_MyMessages)-1
       app_messages.m_MyMessages(i)=app_messages.m_MyMessages(i+1)
     next
   endif



app_messages.m_MyMessages(i)=app_messages.m_MyMessages(i+1)
(для пользовательского типа)
не подведет?
Или правильнее:
Код: vbnet
1.
2.
3.
app_messages.m_MyMessages(i).m_type =app_messages.m_MyMessages(i+1).m_type 
app_messages.m_MyMessages(i).m_parameter =app_messages.m_MyMessages(i+1).m_parameter
... 



Вот это наверно излишки (на другой код глядючи)
Код: vbnet
1.
2.
3.
4.
5.
Private Type AppMessages
  m_MyMessages() As MyMessage
End Type

Public app_messages As AppMessages



Достаточно думаю
Код: vbnet
1.
Public AppMessages() As MyMessage
...
Рейтинг: 0 / 0
13.06.2013, 17:53
    #38296667
Бенедикт
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
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 свою библиотеку типов, компилируем, ссылаемся.
...
Рейтинг: 0 / 0
13.06.2013, 17:59
    #38296684
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
Кстати говоря
Akina различить варианты "определён, но не инициализирован" и "определён и инициализирован", не задействуя обработчик ошибок, трудновато
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Dim a() ' As Long, String ...

If (Not a) = -1 Then
    Debug.Print "array as not been initialized"
Else
    Debug.Print "array as been initialized " & UBound(a)
End If

ReDim a(2)

If (Not a) = -1 Then
    Debug.Print "array as not been initialized"
Else
    Debug.Print "array as been initialized " & UBound(a)
End If


Этого тоже не найдешь в документациях, но работает как часы. Впрочем, как и коллекция.
...
Рейтинг: 0 / 0
13.06.2013, 18:03
    #38296695
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
Бенедикт"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 нельзя сделать публичный класс.
...
Рейтинг: 0 / 0
13.06.2013, 18:21
    #38296745
ВМоисеев
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как грамотно организовать "очередь сообщений"
>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 (изССД == ичССД) ичССД = (++ичССД) % рцмССД; //-- При необходимости изменим индекс чтения
}

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

С уважением, Владимир.
...
Рейтинг: 0 / 0
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / А как грамотно организовать "очередь сообщений" / 25 сообщений из 26, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]