Асинхронная обработка в ADO

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
MOV
Постоялец
Постоялец
 
Сообщения: 414
Зарегистрирован: 13.03.2004 (Сб) 15:13
Откуда: Санкт-Петербург

Асинхронная обработка в ADO

Сообщение MOV » 14.08.2006 (Пн) 14:38

Как можно сделать, чтобы
при вызове

AODDB.Connection.execute "my_procedure"

чтобы прога не висла.

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

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 14.08.2006 (Пн) 14:58

Почитай про аргумент Option, в частности, про флаг adAsyncExecute.
Lasciate ogni speranza, voi ch'entrate.

MOV
Постоялец
Постоялец
 
Сообщения: 414
Зарегистрирован: 13.03.2004 (Сб) 15:13
Откуда: Санкт-Петербург

Сообщение MOV » 14.08.2006 (Пн) 15:37

Спасибо! Оно!!! Ура! :)

MOV
Постоялец
Постоялец
 
Сообщения: 414
Зарегистрирован: 13.03.2004 (Сб) 15:13
Откуда: Санкт-Петербург

Сообщение MOV » 14.08.2006 (Пн) 17:13

в догонку как динамически созадвать новое соединение

то есть допустим ADODB.Connection.execute "myprocedure"
запускаю с флагом adAsyncExecute,
все отлично проца запустилась,
но мне надо (если необходимо, запустить еще несколько сессий с этой процедурой (с другими параметрами)) сколько сессий заранее еизвестно.
То есть надо как-то динамически создавать новое ADODB connection и экзекутить его.
Может как-то создать динамический массив объектов этого типа?

ааа все. получилось:

да типа такого :

Код: Выделить всё
Dim Cn() As ADODB.Connection

Private Sub Command1_Click()
                Static cnt As Long
                cnt = cnt + 1
                ReDim Preserve Cn(cnt)
                Set Cn(cnt) = New ADODB.Connection
                Cn(cnt).ConnectionString = "mystring"
                Cn(cnt).Open
                Cn(cnt).Execute "truncate table trace", , 16
                cnt = cnt + 1
                ReDim Preserve Cn(cnt)
                Set Cn(cnt) = New ADODB.Connection
                Cn(cnt).ConnectionString = "mystring"
                Cn(cnt).Open
                Cn(cnt).Execute "truncate table trace", , 16
End Sub

MOV
Постоялец
Постоялец
 
Сообщения: 414
Зарегистрирован: 13.03.2004 (Сб) 15:13
Откуда: Санкт-Петербург

Сообщение MOV » 05.09.2006 (Вт) 11:37

Вот такой код:

Код: Выделить всё
Dim WithEvents CN As ADODB.Connection
Dim WithEvents RS As ADODB.Recordset

Private Sub CN_ConnectComplete(ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pConnection As ADODB.Connection)
RS.ActiveConnection = CN
End Sub

Private Sub Command1_Click()
Set CN = New ADODB.Connection
Set RS = New ADODB.Recordset
CN.ConnectionString = "Provider=OraOLEDB.Oracle.1;Persist Security " & _
                                "Info=False;User ID=us; PASSwORD=pass; Data Source=source"
CN.Open
RS.Open "select field1, sum(field2) from mytable group by field1", , , , 16
RS.MoveFirst
End Sub


Хочу открыть рекордсет асинхронно, чтобы прога не висла при выполнении запроса, но какое событие надо отлоить, чтобы увидеть, что запрос уже выполнен и можно продолжать работу (RS.MoveFirst)?
Ни одно из событий не срабатывает.
Близко к истине событие RS_FetchComplete но как его вызвать (метода fetch у рекордсета не вижу :( есть filter но как его юзать и вызовет ли он фетч_комплит?).
Или это надо делать как-то по другому?

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 05.09.2006 (Вт) 11:46

Код: Выделить всё
Private Sub rs_FetchComplete(ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pRecordset As ADODB.Recordset)
    bComplete = True
    'ЗДЕСЬ!!!
End Sub

Private Sub rs_FetchProgress(ByVal Progress As Long, ByVal MaxProgress As Long, adStatus As ADODB.EventStatusEnum, ByVal pRecordset As ADODB.Recordset)
    Me.lblRecordCount.Caption = "Найдено записей: " & Me.rs.RecordCount
End Sub

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 05.09.2006 (Вт) 11:51

Код: Выделить всё
Dim WithEvents CN As ADODB.Connection
Dim WithEvents RS As ADODB.Recordset

Private Sub CN_ConnectComplete(ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pConnection As ADODB.Connection)
    RS.Open "select field1, sum(field2) from mytable group by field1", cn, , , 16
End Sub

Private Sub Command1_Click()
    Set CN = New ADODB.Connection
    Set RS = New ADODB.Recordset
    CN.ConnectionString = "Provider=OraOLEDB.Oracle.1;Persist Security " & _
    "Info=False;User ID=us; PASSwORD=pass; Data Source=source"
    CN.Open
End Sub

Private Sub RS_FetchComplete(pError As Error, adStatus As EventStatusEnum, pRecordset As Recordset)
    RS.MoveFirst
End Sub
Лучший способ понять что-то самому — объяснить это другому.

MOV
Постоялец
Постоялец
 
Сообщения: 414
Зарегистрирован: 13.03.2004 (Сб) 15:13
Откуда: Санкт-Петербург

Сообщение MOV » 05.09.2006 (Вт) 12:28

Оба варианта не проходят.
Я же говорю, что событие ФетчКомплит Не возникает
ранво как и события rs_FetchProgress

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 05.09.2006 (Вт) 13:33

RS.Open "select field1, sum(field2) from mytable group by field1", CN, , , adAsyncFetch (32)

С какого потолка значения констант берешь?
Лучший способ понять что-то самому — объяснить это другому.

MOV
Постоялец
Постоялец
 
Сообщения: 414
Зарегистрирован: 13.03.2004 (Сб) 15:13
Откуда: Санкт-Петербург

Сообщение MOV » 05.09.2006 (Вт) 13:59

да все равно не работает хоть 16, хоть 32 хоть просто adAsyncFetch :)
может черканете реально работающий пример где бы отработало событие FetchComplete?

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 05.09.2006 (Вт) 14:07

Код: Выделить всё
  Set cn = New ADODB.Connection
  cn.CommandTimeout = 0
  cn.ConnectionTimeout = 30
  cn.CursorLocation = adUseClient
  cn.Open modADO.GetConnectionString
 
  Set rsEvents = New ADODB.Recordset
  rsEvents.CursorLocation = adUseClient
  rsEvents.PageSize = 100
  rsEvents.CacheSize = 1000
  Set rsEvents.ActiveConnection = cn
  rsEvents.Open SQL, , adOpenStatic, adLockReadOnly, adAsyncFetchNonBlocking
 
 
  Me.lblRecordCount.Caption = "Найдено записей: " & rsEvents.RecordCount
 
  Set dtgEvents.DataSource = rsEvents


остальное ты уже видел

MOV
Постоялец
Постоялец
 
Сообщения: 414
Зарегистрирован: 13.03.2004 (Сб) 15:13
Откуда: Санкт-Петербург

Сообщение MOV » 05.09.2006 (Вт) 14:43

во. спасибо. работает классно.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 05.09.2006 (Вт) 16:06

Забыл сказать, FetchComplete произойдет только с клиентским рекордсетом, когда все записи отданы.
Вложения
fetchTest.rar
(1.54 Кб) Скачиваний: 154
Лучший способ понять что-то самому — объяснить это другому.

MOV
Постоялец
Постоялец
 
Сообщения: 414
Зарегистрирован: 13.03.2004 (Сб) 15:13
Откуда: Санкт-Петербург

Сообщение MOV » 14.09.2006 (Чт) 9:54

Сессия вываливается в некативную.
Делаю так:
Код: Выделить всё
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Dim CNR() As ADODB.Connection
Dim WithEvents CN As ADODB.Connection
Dim WithEvents RS As ADODB.Recordset
Dim Cstring as String

Private Sub CN_ConnectComplete(ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pConnection As ADODB.Connection)
    RS.ActiveConnection=CN
End Sub

Private Sub Command1_Click()
'АСИНХРОННО ЗАПУСКАЮ ПРОЦУ:   
    Set CNR(0) = New ADODB.Connection
    Cstring="Provider=OraOLEDB.Oracle.1;Persist Security " & _
    "Info=False;User ID=us; PASSwORD=pass; Data Source=source"
     CNR(0).Open Cstring
     CNR.Execute "myprocedure",, adAsyncExecute
'ДАЛЕЕ СМОТРЮ КАК ОНА ВЫПОЛНЯЕТСЯ:
     Set CN= New ADODB.Connection
     Set RS= New ADODB.Recordset
     CN.Open Cstring
     cnt=1
     While cnt<>0
           RS.Open "select count(*) cnt from mytable where dt_obr is null"
           if not RS.EOF then
               RS.MoveFirst 
               cnt=RS.Fields("cnt").value
           else
               cnt=0 'необработанных записей не осталось, выходим из цикла
           end if
            RS.Close
           DoEvents
           Sleep 5000   
     Wend
End Sub

Private Sub RS_FetchComplete(pError As Error, adStatus As EventStatusEnum, pRecordset As Recordset)
    RS.MoveFirst
End Sub


Сначала, все работает нормально и видно как обрабатываются записи, но потом сессия с процедурой, которая запущена асинхронно вываливается в неактивную (видно в V$SESSION) (при чем на одном и том же количестве записей), естественно, обработка прекращается и цикл становится бесконечным. Такое происходит не с одной процедурой, с другими - аналогичная картина.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 14.09.2006 (Чт) 11:19

Потому что тут такая дикая мешанина... Вообще непонятно где тут что асинхронно выполняется... Завершения CN_ConnectComplete не ждешь, вернее оно вообще не нужно - соединение открывается без асинхронности... RS_FetchComplete никогда не выполнится... While cnt<>0 ... Sleep 5000 Wend - вообще дикость. Этот цикл блокирует прогу, а если ты им всего лишь ждешь результата выполнения myprocedure, то нафига тогда асинхронность?

Ты бы хоть скачал мой пример, чтобы увидеть, как на самом деле работает асинхронность.
Лучший способ понять что-то самому — объяснить это другому.

MOV
Постоялец
Постоялец
 
Сообщения: 414
Зарегистрирован: 13.03.2004 (Сб) 15:13
Откуда: Санкт-Петербург

Сообщение MOV » 14.09.2006 (Чт) 12:08

Этот цикл блокирует прогу, а если ты им всего лишь ждешь результата выполнения myprocedure, то нафига тогда асинхронность?

Так если не асинхронить, то прога подвисает пока не выполнится екзекуте (это может занять и час), а я хочу, чтобы прога работала легко и непринужденно, поэтому в цикле жду пока закончится обработка плюс вывожу на форму ход выполнения (ну сколько записей осталось обработать). Плюс к этому есть необходимость пускать несколько процедур параллельно, а потом ждать пока они завершаться, поэтому надо асинхронно.
А на счет слип ты прав, может из-за того, что слишком большой слип прога и отваливается - попробую поставить на 1 секунду. Да и слип сам по себе вешает прогу конечно тоже. Делать все это в отдельной тереде было бы круче наверно, но не умею. Да. Пример сейчас скачаю.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 14.09.2006 (Чт) 12:13

А знаешь, чем тебе грозит DoEvents в цикле?
Lasciate ogni speranza, voi ch'entrate.

MOV
Постоялец
Постоялец
 
Сообщения: 414
Зарегистрирован: 13.03.2004 (Сб) 15:13
Откуда: Санкт-Петербург

Сообщение MOV » 14.09.2006 (Чт) 12:41

А знаешь, чем тебе грозит DoEvents в цикле?

Чем? :(
Неужели нельзя у меня без него ведь форма не будет перерисовываться.
1. Блин может тогда кто-то сбросит как в отдельном треде запустить процедуру на серваке?
2. в принципе можно сбросить скрипт запускающий процу на винт, а потом шелом запустить sqlplus на выполнение этого скрипта в скрытом режиме, но это коряво как-то и труднее отловить оишбку, если проца в склплюсе ругнется вдруг.
В общем, в отдельном потоке было бы лучше. Пойду искать инфу по многопоточности :(

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 14.09.2006 (Чт) 13:27

Тебе уже дали нормальное решение.
Запускаешь процедуру асинхронно.
Устанавливаешь специальный флаг.
Блокируешь все "лишние" элементы управления.
В процедуре _Complete сбрасываешь флаг, восстанавливаешь элементы управления и продолжаешь необходимые действия.
Lasciate ogni speranza, voi ch'entrate.

Wasup!
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 120
Зарегистрирован: 21.06.2005 (Вт) 11:09

Сообщение Wasup! » 03.11.2006 (Пт) 13:52

Продолжу в этом топике.
Пытаюсь сделать асинхронное выполнение запросов.
У меня получилось сделать это только с проверкой rs.state в таймере.
Думаю, что правильней пользоваться событиями, как описано выше, но у меня событие fetchComplete не возникает. Пробовал
разные варианты. Пример прикладываю.

Также просьба посмотреть, правильно ли реализована отмена асинхронного запроса и высвобождение ресурсов при этой отмене.
Есть подозрение, что что-то там не так - при отмене большого запроса программа подвисает на 5-20 сек.
Вложения
Ado events.zip
(4.93 Кб) Скачиваний: 125

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 03.11.2006 (Пт) 14:08

У тебя VB не версии 5, случаем?
И Timer1 свой злостный отключи.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Wasup!
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 120
Зарегистрирован: 21.06.2005 (Вт) 11:09

Сообщение Wasup! » 03.11.2006 (Пт) 14:23

Нет 6-ой. Ado подключен 2.7
Событие не возникает и при включенном и при выключенном таймере.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 03.11.2006 (Пт) 14:31

Попробуй задать rs.Properties("Initial Fetch Size") = 0
К тому же, не Fetch, а FetchNonBlocking.
Lasciate ogni speranza, voi ch'entrate.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 03.11.2006 (Пт) 14:34

2.8 поставь, и asyncexecute убери.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас


Вернуться в Visual Basic 1–6

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

Сейчас этот форум просматривают: AhrefsBot, Mail.ru [бот] и гости: 13

    TopList