Multi-Threading на VB

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

Multi-Threading на VB

Сообщение Scuder » 28.05.2004 (Пт) 17:18

Возможно?
Задача такая: есть программа, которая отсылает на удалённый сервер информацию. Информации много, отсылать надо постоянно. Встал вопрос о создании отдельных потоков. Как это можно реализовать?

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 28.05.2004 (Пт) 17:28

Если у тебя VB5 - смотри MSDN, там есть примеры с многопоточностью на VB.
Если шестой - лучше даже не пытаться, ибо как раз с появлением VB6 Microsoft убрала эти примеры. Видимо, они переписали часть библиотек, и какие-то функции получились нереентерабельными. Лучше сразу тогда на НЕТ переходи - там больше возможностей в этом плане.

Scuder
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 334
Зарегистрирован: 17.08.2002 (Сб) 13:18
Откуда: Moscow, Russia

Сообщение Scuder » 28.05.2004 (Пт) 17:34

Шестой. Но.. я не верю, что нет выхода..

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 28.05.2004 (Пт) 17:39

Я, наверное, неправильно выразился.

У тебя имеется ненулевая вероятность того, что твое многопоточное приложение заработает как надо. Но никто и никогда не поручится, что оно всегда и на любых платформах будет работать именно так. И никто тебе не скажет, где именно у тебя проблемы.

Scuder
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 334
Зарегистрирован: 17.08.2002 (Сб) 13:18
Откуда: Moscow, Russia

Сообщение Scuder » 28.05.2004 (Пт) 17:52

Ну это понятно..

А если DLL создать? И вызывать функцию? И если будут 2 одновременных вызова, будет 2 потока?

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 28.05.2004 (Пт) 18:11

Нет. Ты сначала делаешь один вызов, он отрабатывает, потом второй, потом он отрабатывает. Никакой многопоточности.
Есть один способ, который Microsoft считает честным, поэтому он описан в MSDN. Заключается он вот в чем.

1. Ты пишешь ActiveX EXE, который работает в режиме DCOM-сервера.
2. Из клиента (который Standard EXE) ты вызываешь метод класса со своего сервака. Выполнение твоего потока (и процесса) приостанавливается и передается на сервер.
3. Сервер понимает, что от него хотят, но вместо того, чтобы выполнить запрос, он мгновенно возвращает управление твоему клиенту. НО! Перед тем, как это сделать, он запускает свой внутренний таймер (допустим, на 50 мс) и запоминает в своих внутренних структурах, что именно он должен сделать.
4. Выполнение клиента возобновляется.
5. На серваке срабатывает таймер. В этот момент он начинает процессить то, что ты от него хотел, вызвав его метод.
6. Когда сервак заканчивает свою работу, он файрит ивент, который ловится у тебя на клиенте. Результаты работы сидят в аргументах этого события.

Voila! Полнейшая иллюзия асинхронности, слегка омраченная лишь тем, что тебе нужно как-то засунуть таймер в программу без визуального интерфейса. Но я уверен, что уж с этим-то ты справишься :) .

P.S. Чтобы твой сервер приложений был действительно многопоточным, в свойствах проекта выставь галку Unattended execution (не помешает, поверь) и в разделе Threading Model переведи опшн в положение Thread per Object. Ну и, конечно, классы должны быть реентерабельными.

codemaster
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 604
Зарегистрирован: 13.02.2004 (Пт) 13:35

Re: Multi-Threading на VB

Сообщение codemaster » 28.05.2004 (Пт) 19:15

Scuder писал(а):Возможно?
Задача такая: есть программа, которая отсылает на удалённый сервер информацию. Информации много, отсылать надо постоянно. Встал вопрос о создании отдельных потоков. Как это можно реализовать?


Иногда многопоточные приложения работают гораздо медленнее однопоточных. Так что стоит крепко подумать

BuilderSoft
Постоялец
Постоялец
 
Сообщения: 350
Зарегистрирован: 21.09.2002 (Сб) 10:13

Сообщение BuilderSoft » 29.05.2004 (Сб) 22:20

я слышал на UNIX можно что то похожее сделать там можно страницы менять размеры к CPU относительно и потоки
Нет глупых,
Один узнал раньше других
אין א-אפשר

GM
programador
programador
 
Сообщения: 1427
Зарегистрирован: 24.06.2003 (Вт) 15:56
Откуда: 194.67.52.100

Сообщение GM » 30.05.2004 (Вс) 1:25

Я если я правильно понял ,то вот пример:
Вложения
multithreading_in_vb.zip
(9.44 Кб) Скачиваний: 83

BuilderSoft
Постоялец
Постоялец
 
Сообщения: 350
Зарегистрирован: 21.09.2002 (Сб) 10:13

Сообщение BuilderSoft » 30.05.2004 (Вс) 19:23

GM писал(а):Я если я правильно понял ,то вот пример:


Круто спасибо

но многопоточность не совсем это

спасибо
Нет глупых,
Один узнал раньше других
אין א-אפשר

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 30.05.2004 (Вс) 21:42

BuilderSoft писал(а):...
но многопоточность не совсем это
...


А что же такое многопоточность, по-твоему???

GM
programador
programador
 
Сообщения: 1427
Зарегистрирован: 24.06.2003 (Вт) 15:56
Откуда: 194.67.52.100

Сообщение GM » 31.05.2004 (Пн) 1:15

Да действительно?

Scuder
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 334
Зарегистрирован: 17.08.2002 (Сб) 13:18
Откуда: Moscow, Russia

Сообщение Scuder » 31.05.2004 (Пн) 10:30

Господа, это действительно многопоточность, судя по Диспетчеру задач, но вы не пробовали скомпилить EXE'шник? VB6 не переваривает Terminate Thread: "Память не может быть read".. Ошибка вылетает при закрытии приложения, если запустить больше 2 и более одинаковых потоков.. Впрочем, компилятор тоже вылетает..

2 Ennor: А ты уверен, что этот ActiveX EXE действительно будет создавать несколько потоков? :-) Асинхронности я могу и из своего приложения добиться.. Но когда я создаю 10 псевдо-потоков, а точнее вызываю функцию одновременно 10 раз, время ожидания ответа от сервера в эти 10 раз и увеличивается.. Даже не в 10, а раз в 50..

codemaster:
Иногда многопоточные приложения работают гораздо медленнее однопоточных. Так что стоит крепко подумать


:-) Я уже подумал. :-) Короче. Запрос от сервера приходит в течение 3-10 секунд. Это если 1 поток. Если я 10 раз вызываю одну и ту же функцию, ответ приходит почти сразу на 10 запросов через 1-3 минуты. А вот если а запущу 10 EXE'шников, которые, соответственно, создадут 10 независимых потоков, все получают ответ через 3-10 секунд.

Вот я и думаю: неужели, это единственный выход??

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 31.05.2004 (Пн) 10:42

Если ты выставишь ему Threading Model в Thread per Object, то это и будет честное многопоточное приложение. Каждый экземпляр класса такого объекта будет создаваться в отдельном потоке - можешь посмотреть в Spy++ окно Threads. Кстати, и свое посмотри - какие там у тебя реальные "потоки" :? .
ЕХЕ я компилял - не люблю запускать такие вещи из-под среды. Все работает нормально, пока не начинаешь путать кнопки :) . Правда, у меня ХР.

И объясни ты мне, пожалуйста, как это ты на VB ухитряешься *одновременно* вызывать функцию 10 раз? И что такое псевдопотоки? И как Task Manager может показать потоки, если он в принципе показывает только процессы?

Может, сначала матчасть подучить, как любят говаривать здешние модераторы?..

Scuder
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 334
Зарегистрирован: 17.08.2002 (Сб) 13:18
Откуда: Moscow, Russia

Сообщение Scuder » 31.05.2004 (Пн) 11:01

2 Ennor

Матчасть может и стоит подучить, но

...хомячков этих я в детстве отлюбил.

(с) "Мама не горюй"

И объясни ты мне, пожалуйста, как это ты на VB ухитряешься *одновременно* вызывать функцию 10 раз?


Код: Выделить всё
Function Payment(ServiceID As String, PhoneNumber As String, Amount As String, TransactionNumber As String) As String

Dim Pi As Integer

For Pi = 0 To 9
If ConFree(Pi) = True Then GoTo Ne1
Next Pi

Exit Function

Ne1:
ConFree(Pi) = False
Me.PTime(Pi) = "0"

Me.Status(Pi).Caption = "[" & CStr(TransactionNumber) & "] Авторизация..."
DoEvents

For a1(Pi) = 1 To 2

Query(Pi) = ""
Query(Pi) = [cut]
Con(Pi).open "POST", "https://[cut]/xml.jsp", True

Con(Pi).setRequestHeader "Accept-Language", "ru, en"
Con(Pi).setRequestHeader "Accept-Charset", "windows-1251;q=1"
Con(Pi).setRequestHeader "Content-Type", "text/xml; charset=windows-1251"
Con(Pi).setRequestHeader "Content-Length", CStr(Len(Query(Pi)))
Con(Pi).send Query(Pi)

Do While Con(Pi).readyState <> 4
    Sleep (20)
    DoEvents
Loop

Dim Answer(10) As String
Answer(Pi) = Con(Pi).responseText
DoEvents

[обработка ответа]

If a1(Pi) = 1 Then
    Me.Status(Pi).Caption = "[" & CStr(TransactionNumber) & "] Проведение платежа..."
    DoEvents
Else
    Me.Status(Pi).Caption = "[" & CStr(TransactionNumber) & "] Платёж успешно проведён."
    DoEvents
End If

Next a1(Pi)

ConFree(Pi) = True

Exit Function

End Function


Прошу не обращать внимание на такие вещи как TransactionNumber As String и CStr(TransactionNumber). Не в этом суть.

Вот такую функцию можно вызвать 10 раз. Соединение асинхронное, поэтому, по-идее, каждый вызов должен завершаться самостоятельно, а не в связке с остальными. ПОЧТИ так и происходит. Но повторяю: время ответа от сервера увеличивается в десятки раз..

И что такое псевдопотоки?


Тут я не имел ввиду некой эмуляции. А всего лишь то, что написал выше.

И как Task Manager может показать потоки, если он в принципе показывает только процессы?


Диспетчер задач - Процессы - Вид - Выбор столбцов - Счётчик потоков.

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 31.05.2004 (Пн) 19:32

Хм. Начну с конца.
Task Manager показывает не потоки процесса, а их количество. С программами, написанными на VB6, на эту цифру лучше вообще не смотреть - только запутаешься. Поэкспериментируй с программами-пустышками, сам увидишь. Только не из-под среды их запускай, а компиляй - разница огромная.
Далее. Если ты хочешь, чтобы все твои коннекты работали действительно асинхронно и независимо друг от друга, то тебе необходимо обеспечить эту независимость на всем их протяжении. Для этого ты должен быть уверен, что твой сервер приложений (кстати, это не JONAS, часом?) создает как минимум по одному потоку на каждый твой коннект и всю работу с этим коннектом выполняет именно в его трэде. Ты можешь это гарантировать? Ибо, если он работает с твоими соединениями в одном трэде, то знаешь, что он будет с ними делать? Он поставит их в очередь. Отсюда - задержки для всех соединений сразу. Что же касается твоей части, то коннекты нужно открывать вручную и ни в коем разе их не клонировать. Но это так, для полноты картины, скорее.

Ну и последнее. Возможно, у тебя банально не хватает вычислительной мощности/памяти на серваке. Посмотри его загрузку, погоняй Performance Counter'ы. Не исключено, что все решится покупкой двухпроцессорного юнита или дополнительного гига оперативки :) .

Scuder
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 334
Зарегистрирован: 17.08.2002 (Сб) 13:18
Откуда: Moscow, Russia

Сообщение Scuder » 01.06.2004 (Вт) 10:38

Начну сначала.. :-)

Task Manager показывает не потоки процесса, а их количество.


Тут я не совсем понял.. Количество чего? Он показывает не только сами процессы, но и количество потоков внутри каждого. Наглядный пример выложен в этом топике. Если скомпилить EXE, то будет видно количество потоков в процессе..

Для этого ты должен быть уверен, что твой сервер приложений (кстати, это не JONAS, часом?) создает как минимум по одному потоку на каждый твой коннект и всю работу с этим коннектом выполняет именно в его трэде.


Ты имеешь в виду веб-сервер? Тогда не JONAS - jakarta tomcat. И я могу гарантировать, что он создаёт потоки, поскольку, как я уже писал выше, если я запущу 10 коннектов из 10 одинаковых EXE'шников, то время ожидания ответа - стандартное (3-10 секунд).

Что же касается твоей части, то коннекты нужно открывать вручную и ни в коем разе их не клонировать.


Так я их и открываю вручную:

Код: Выделить всё
Dim Con(10) As MSXML2.XMLHTTP

For i(1) = 0 To 9
Set Con(i(1)) = New MSXML2.XMLHTTP
ConFree(i(1)) = True
Next i(1)


Как ещё их можно открыть?

Возможно, у тебя банально не хватает вычислительной мощности/памяти на серваке. Посмотри его загрузку, погоняй Performance Counter'ы. Не исключено, что все решится покупкой двухпроцессорного юнита или дополнительного гига оперативки


Конфигурация кластера: 2 сервера по 2xXeon 3.06 по 3 Gb памяти в каждом серваке по 2 raid 5 массива на seagate barracuda ultra 320 15k rpm. Между ними поднят heartbeat и оракловая репликация.

Так что, я думаю, на сервер пенять не надо.. У меня такой вот вопрос.. Понятно, что используется MSXML, но не понятно как она работает.. Ведь если посмотреть приведённый код, я могу создать 10 асинхронных подключений. Но почему они так загружают канал, и не работают реально как 10 потоков? :-(

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 01.06.2004 (Вт) 11:00

Круто. Респект :) . Сразу виден подход делового человека.

Учитывая все сказанное тобой, могу сделать такое предположение. Единственное, что приходит в голову, так это то, что томкат производит агрегацию коннектов в зависимости от клиентского процесса. Проще говоря: ты запускаешь одного клиента с 10 коннектами, он видит, что ProcessID у них всех один и тот же, и сует их все в один трэд. Ты запускаешь 10 процессов, он видит, что к нему пришли 10 разных клиентов, и создает по трэду на коннект (в данном случае - на клиентский процесс). Только если так.

Либо... Либо у тебя все-таки клиент ни фига не асинхронный. Это нужно тайм-стэмпами выяснять. После каждой операции с коннектом в массиве поставь:
Код: Выделить всё
Debug.Print Now & " " & Pi

Сразу и увидишь.

Scuder
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 334
Зарегистрирован: 17.08.2002 (Сб) 13:18
Откуда: Moscow, Russia

Сообщение Scuder » 01.06.2004 (Вт) 11:56

Круто. Респект . Сразу виден подход делового человека.

:-)

ты запускаешь одного клиента с 10 коннектами, он видит, что ProcessID у них всех один и тот же, и сует их все в один трэд. Ты запускаешь 10 процессов, он видит, что к нему пришли 10 разных клиентов, и создает по трэду на коннект (в данном случае - на клиентский процесс). Только если так.


Нет. К сожалению, не так. Сервер не видит никаких ProcessID.

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

Причём, как правило, ответ на все 10 запросов я получаю одновременно..

Код: Выделить всё
Debug.Print Now & " " & Pi


Блин, вот только сейчас проверил! :-(
Как это назвать? Псевдоасинхронность или полусинхронность?? :-(

Код: Выделить всё
Do While Con(Pi).readyState <> 4
    Sleep (20)
    DoEvents
    Debug.Print Now & " " & Pi
Loop


Короче, запустил 2 коннекта, и что увидел в Immediate? Что идёт обработка последнего коннекта! И уже когда ответ на него пришёл, тут же обработался 1-й, ответ на который, видимо, был готов гораздо раньше.. Таким образом, объяснилось получение ответа на все коннекты одновременно. Гм. Значит и решилась проблема "постановки в очередь". Осталось сделать так, чтобы функция не ждала результата обработки последнего запроса, а выдавала все предыдущие результаты..


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

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

Сейчас этот форум просматривают: Yandex-бот и гости: 30

    TopList