Особенности асинхронной обработки данных (вопрос)

Разговоры на любые темы: вы можете обсудить здесь какой-либо сайт, найти единомышленников или просто пообщаться...
alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Особенности асинхронной обработки данных (вопрос)

Сообщение alibek » 17.04.2004 (Сб) 11:42

Привет, форумчане :)
Есть у меня парочка вопросов к всезнающему All :)

Итак, имеется у меня прога. Прога отсылает какие-то запросы и получает ответы. Все усложняется тем, что этот процесс происходит асинхронно. А при такой специфике возникает так много нюансов и особенностей, что я уже задолбался :)

Вводная:
~~~~~~
Запросы бывают разных типов. Некоторые выглядят как "запросить текущее время сервера", с их обработкой проблем не возникает, надо просто обрабатывать их при получении.
Однако есть и другие запросы. К примеру, в основной форме есть команда меню "Изменить список категорий". При ее выборе открывается дочерняя форма, в которой отображается этот самый список и имеется интерфейс для его редактирования.
Сложность тут в том, что при выборе команды "Изменить список категорий" нельзя сразу открыть дочернюю форму. Надо вначале отправить соответствующий запрос, а только по приходу ответа открыть эту форму (с заполненным списком).

Решение:
~~~~~~
На данный момент у меня это реализовано подобным образом.
Имеется такой фрагмент (код чуть упрощен, на практике он больше для оптимизации поиска):
Код: Выделить всё
Public Enum Actions
  Action1
  Action2
  ...
End Enum

Private Const msgMax As Long = 10
Private Type MsgBuffer
  Clock As Long
  Timeout As Long
  Action As Actions
  MsgID As String
  MsgQuery As String
End Type
Private msg(1 To msgMax) As MsgBuffer

Public Sub AddMsgBuffer(MsgID As String, Query As String, Optional ByVal Action As Actions, Optional ByVal Timeout As Long)
If msgCount >= msgMax Then Exit Sub
msgCount = msgCount + 1
With msg(msgCount)
  .Clock = GetTickCount()
  .Timeout = Timeout
  .Action = Action
  .MsgID = MsgID
  .MsgQuery = Query
End With
End Sub

Public Sub RemoveMsgBuffer(MsgID As String)
Dim I As Long, I0 As Long
If Len(MsgID) = 0 Then
  msgStart = 1
  msgCount = 0
  Exit Sub
End If
For I = 1 To msgCount
  If msg(I).MsgID = MsgID Then
    I0 = I
    Exit For
  End If
Next I
If I0 = 0 Then Exit Sub
For I = I0 To msgCount - 1
  msg(I) = msg(I + 1)
Next I
msgCount = msgCount - 1
End Sub


Когда приложение формирует запрос, то вызывается процедура ClientRequest, в которую передается действие (Actions), запрос и параметры для запроса. В этой процедуре формируется строка запроса и одновременно вызывается AddMsgBuffer. MsgID является уникальным идентификатором сообщения.
Когда приходит ответ, в ответе передается идентификатор MsgID (идентификатор того сообщения, на которое и был сформирован запрос). По этому MsgID определяется Action и MsgQuery. После получения и обработки ответа выполняется RemoveMsgBuffer.

Во всех дочерних формах имеются Friend-процедуры ExtControl(...), через которые основная форма передает полученные ответы. К примеру, в дочерней форме был добавлен новый элемент в список. Эта форма вызывает ClientRequest(Action:=AddListItem,...) с необходимыми параметрами и блокируется (Enabled=False, MousePointer=...). Когда приходит ответ от сервера, соответствующая процедура делает парсинг ответа и определяет, на какой запрос (вернее, на какой Action) пришел ответ. Если это AddListItem, то ответ передается в frmListEditor.ExtControl(Action, ResultCode, Data). В процедуре ExtControl этот ответ обрабатывается (элемент добавляется в список или показывается сообщение об ошибке) и форма снова в режиме ожидания.

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

Лучше всего было бы обойтись вообще без очереди запросов, но как это сделать при асинхронной передаче данных, я не представляю. Правда можно попытаться включить на сокете режим синхронной передачи данных, но это крайний случай.
Кто уже сталкивался с подобными задачами, может вы что посоветуете? А то моя реализация работает, но даже мне она кажется слишком усложненной и ненадежной.

Заранее спасибо :)
Lasciate ogni speranza, voi ch'entrate.

Вернуться в Народный треп

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 108

    TopList