Выход из потока. Планировщик.

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Jack Ferre
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 132
Зарегистрирован: 17.02.2014 (Пн) 14:31
Откуда: Казахстан, Костанай

Выход из потока. Планировщик.

Сообщение Jack Ferre » 23.07.2014 (Ср) 17:54

Допустим, я не использую CreateThread :mrgreen: , но имеется callback-функция, вызываемая из другого (правильно инициализированного) потока. Эта функция вызывает функцию, та в свою очередь 10, те еще по 10. Итого: куча потенциально опасных вызовов функций, declared API, методов (своих классов, формы, контролов), рантайма.
"потенциально опасных" - в отличии от CreateThread приложение не падает, но рейзятся бредовые ошибки и фейлятся методы COM объектов.

Хотелось бы услышать советы: как лучше сделать планировщик?

1. Поток оставляет запись в неком списке/коллекции.
Что можно передать?
  • id функции (Long)
  • один пользовательский параметр (Long) (в ООП - указатель на объект)
Как организовать список/коллекцию, чтобы использовать минимум функций рантайма, но с возможностью добавлять и удалять элементы?

2. Как вызывать запланированные функции?
  • VB-шный таймер - нужна VB-форма.
  • В программе без VB-форм - msgloop - неудобно.
  • Самописный таймер. На форуме есть готовый, но он асинхронный (тест3 - улыбнул). В этом же топике есть ссылка на "классический" класс XTimer, но она мертва.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Выход из потока. Планировщик.

Сообщение Хакер » 23.07.2014 (Ср) 19:01

Я ничего не понял.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Jack Ferre
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 132
Зарегистрирован: 17.02.2014 (Пн) 14:31
Откуда: Казахстан, Костанай

Re: Выход из потока. Планировщик.

Сообщение Jack Ferre » 23.07.2014 (Ср) 20:22

Объяснятель с меня плохой :oops:
Главный поток
Поток, вызывающий callback-функцию


ThreadMgr.png
ThreadMgr.png (41.08 Кб) Просмотров: 4103


just for fun
tele.png
tele.png (6.65 Кб) Просмотров: 4101

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Выход из потока. Планировщик.

Сообщение Хакер » 23.07.2014 (Ср) 22:07

А смысл и контекст применения?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Jack Ferre
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 132
Зарегистрирован: 17.02.2014 (Пн) 14:31
Откуда: Казахстан, Костанай

Re: Выход из потока. Планировщик.

Сообщение Jack Ferre » 23.07.2014 (Ср) 22:26

Вернуть выполнение в основной поток.
Заменить следующую схему действий.
Код: Выделить всё
... CreateThread(addressof MyThread, user) ...

Sub MyThread (user as long)
    1 строчка кода способная повешать программу на несколько секунд для которой создан поток
    MyCallback (user) ' сообщение, что действие выполнено
end sub

Sub MyCallback (user as long)
    100500 строчек кода выполняемых вне основного потока
end sub

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Выход из потока. Планировщик.

Сообщение Хакер » 24.07.2014 (Чт) 9:48

Т.е. смысл просто в том, чтобы написать многопоточную программу и отдавать блокирующие задание на участь не-GUI-потоков?
И нет никакого стороннего API, которое безальтернативно вынуждает предоставлять свои callback-и, которые могут быть вызваны в рамках других потоков?

Я правильно понял?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Jack Ferre
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 132
Зарегистрирован: 17.02.2014 (Пн) 14:31
Откуда: Казахстан, Костанай

Re: Выход из потока. Планировщик.

Сообщение Jack Ferre » 24.07.2014 (Чт) 18:18

Т.е. смысл просто в том, чтобы написать многопоточную программу и отдавать блокирующие задание на участь не-GUI-потоков?

В случае CreateThread.
И нет никакого стороннего API, которое безальтернативно вынуждает предоставлять свои callback-и, которые могут быть вызваны в рамках других потоков?

Такой API есть.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Выход из потока. Планировщик.

Сообщение Хакер » 24.07.2014 (Чт) 19:30

Jack Ferre писал(а):Такой API есть.

Тогда повторяю вопрос о контексте применимости и даю тебе ещё раз возможность описать суть.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Jack Ferre
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 132
Зарегистрирован: 17.02.2014 (Пн) 14:31
Откуда: Казахстан, Костанай

Re: Выход из потока. Планировщик.

Сообщение Jack Ferre » 24.07.2014 (Чт) 19:37

Bass audio library © Un4seen development

Код: Выделить всё
' CPlayer.cls
... Call BASS_ChannelSetSync(hChannel, BASS_SYNC_END Or BASS_SYNC_ONETIME, 0, AddressOf SYNCPROC_End, ObjPtr(Me)) ...

Public Sub Sync_End
    ...
End Sub

' modPlayer.bas
Sub SYNCPROC_End(ByVal handle As Long, ByVal channel As Long, ByVal data As Long, ByVal user As Long)
    Dim player As CPlayer
    ObjSet player, user    ' __vbaObjSetAddref
    player.Sync_End
End Sub

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Выход из потока. Планировщик.

Сообщение Хакер » 25.07.2014 (Пт) 19:28

Окей. Почитал документацию по bass.dll. Там сказано, что библиотека создаёт специальный отдельный поток, в рамках которого вызывает callback-и (кроме одного случая).

Вопрос в том, что за работа должна выполняться по callback-e. Как ты хочешь распределить работу между главным потоком и вспомогательным? Тебе нужно решение на один раз или какое-то очень универсальное?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Jack Ferre
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 132
Зарегистрирован: 17.02.2014 (Пн) 14:31
Откуда: Казахстан, Костанай

Re: Выход из потока. Планировщик.

Сообщение Jack Ferre » 25.07.2014 (Пт) 21:22

Хакер писал(а):Окей. Почитал документацию по bass.dll.

Зачем оно вам? Вы мне на слово не поверили?
Хакер писал(а):что за работа должна выполняться по callback-e

В случае BASS_SYNC_END (который я привел в примере) - открыть след. трек из плейлиста - куча вызовов (Bass API, Win API, COM), в которой так же может встретиться вызов IMSWinsockControl.SendData, а он фейлится в 90% случаев вне главного потока.
Хакер писал(а):Как ты хочешь распределить работу между главным потоком и вспомогательным?

Всё главному.
Хакер писал(а):Тебе нужно решение на один раз или какое-то очень универсальное?

Универсальное.

Начну ка я писать эскиз задумки.

Jack Ferre
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 132
Зарегистрирован: 17.02.2014 (Пн) 14:31
Откуда: Казахстан, Костанай

Re: Выход из потока. Планировщик.

Сообщение Jack Ferre » 25.07.2014 (Пт) 22:32

Пример с использование CreateThread. С callback-функциями аналогично.
ThreadProxy.rar
(2.83 Кб) Скачиваний: 102


:!: В таком виде работает только в IDE.
:!: Если одновременно создать более одного дополнительного потока, после закрытия программы IDE упадёт.

The trick
Постоялец
Постоялец
 
Сообщения: 781
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: Выход из потока. Планировщик.

Сообщение The trick » 26.07.2014 (Сб) 0:03

Пример с использование CreateThread. С callback-функциями аналогично.

Так нельзя создавать потоки. Где инициализация?
Создавай ActiveX DLL, из нее создавай новый объект через CreateInstance, предварительно выполнив OleInitilize. Все API, вызываемые вне инициализации объявляй в tlb.
К примеру DLL с методом Message (показывает MsgBox), Threading Model - Apartment:
Код: Выделить всё
Public Function Message(msg As String) As Long
    Message = MsgBox(msg)
End Function

Функция потока из приложения (IID заменить на нужный интерфейс для раннего связывания):
Код: Выделить всё
Public Function ThreadCallback(ByVal lParam As Long) As Long
    Dim clsid As UUID
    Dim iid   As UUID
    Dim out   As Object
   
    CoInitialize ByVal 0&
    CLSIDFromString "{DA82B2F9-52D0-4C50-B2BB-ADE7969ED6FE}", clsid
    CLSIDFromString "{00020400-0000-0000-C000-000000000046}", iid
   
    If CoCreateInstance(clsid, Nothing, CLSCTX_INPROC_SERVER, iid, out) = 0 Then
       
        out.message "tolik"
       
    End If
   
    ExitThread 0
   
End Function

Вызываем:
Код: Выделить всё
Private Declare Function CreateThread Lib "kernel32" (lpThreadAttributes As Any, ByVal dwStackSize As Long, ByVal lpStartAddress As Long, lpParameter As Any, ByVal dwCreationFlags As Long, lpThreadId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long


Private Sub cmdNewThread_Click()
    Dim hThrd As Long
   
    hThrd = CreateThread(ByVal 0&, 0, AddressOf ThreadCallback, 0, 0, 0)
   
    If hThrd Then Caption = "Успех" Else Caption = "Неудача"
   
    CloseHandle hThrd
End Sub



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

Изображение

Если хочешь создавать непосредственно в Standart EXE (как я делал тут к примеру), то не используй потокозависимых функций рантайма либо инициализируй его.
Во-вторых нельзя просто так предавать ссылки на объекты без маршаллинга.
Вложения
InitThread.rar
Пример
(12.29 Кб) Скачиваний: 90
UA6527P

Jack Ferre
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 132
Зарегистрирован: 17.02.2014 (Пн) 14:31
Откуда: Казахстан, Костанай

Re: Выход из потока. Планировщик.

Сообщение Jack Ferre » 26.07.2014 (Сб) 6:48

Кривоус Анатолий писал(а):Все API, вызываемые вне инициализации объявляй в tlb.

100 раз такое на форуме читал, но без какого-либо объяснения. М.б. DllFunctionCall потокозависимая функция? Окай. Кто такие потокозависимые функции? М.б. те, кому нужен TLS.
Jack Ferre писал(а): В таком виде работает только в IDE.

По факту правильно. Но по сути: "Работает только с наличием TLS". Не знаю что такое TLS, но м.б. тот большой красный прямоугольник из картинки про инициализацию контекста? И при создании (не мной) одного и более потоков он таки появляется.

Кривоус Анатолий писал(а):Работает в скомпилированном виде.

Точнее "только в скомпилированном виде". Я нашел почему:
Кривоус Анатолий писал(а):ExitThread 0

В общем случае: зачем такое писать на VB, поток и так вернет 0 при завершении функции. А при необходимости поменять код возврата можно другим способом.
В частном случае: вы убиваете поток при живой ссылке out. IDE падает из-за попытки её освободить.

Стабильные потоки VB в моём текущем представлении - это отсутствие вызова функции Win API CreateThread.
Но так как альтернативы нет, приходится довольствоваться ей.
Проблемы CreateThread с которыми я сталкивался:
  • (Как уже писал) Если одновременно создать более одного дополнительного потока, после закрытия программы IDE упадёт.
  • При закрытии программы в IDE, есть шанс падения IDE.
  • В зависимости от содержания вызываемой функции есть шанс падения программы.
  • В зависимости от содержания вызываемой функции есть шанс падения программы при выходе из потока.
  • Наличие этого "шанса". Размытие границы "Это можно! Это нельзя!"

Я ожидал, что при отсутствии строки CoInitialize ByVal 0& программа упадёт. Так нет - просто неудачное выполнение CoCreateInstance. :?
Кривоус Анатолий писал(а): нельзя просто так предавать ссылки на объекты без маршаллинга

Маршаллинг, что это? Почему, если он так важен, без него всё работает?
К тому же в примере ThreadProxy я не передаю ссылку на объект, а только указатель. После (уже в основном потоке) делаю из него ссылку.


Julia. :shock: А чего это она не падает? Фэн-шуй?


Кривоус Анатолий писал(а):Так нельзя создавать потоки. Где инициализация?

Jack Ferre писал(а):Допустим, я не использую CreateThread, но имеется callback-функция, вызываемая из другого (правильно инициализированного) потока.

The trick
Постоялец
Постоялец
 
Сообщения: 781
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: Выход из потока. Планировщик.

Сообщение The trick » 26.07.2014 (Сб) 9:52

100 раз такое на форуме читал, но без какого-либо объяснения

Поиск: библиотека типов, MIDL, TypeLibrary
Окай. Кто такие потокозависимые функции? М.б. те, кому нужен TLS.

Я тебе не могу предоставить полный список функций и конструкций вызывающих подобные функции. Знаю что COM требует инициализацию рантайма (т.е. любое обращение к App, также невозможно, а значит любой вызов Declare невозможен, т.к. Declare обращается к нему для установки LastDllError), а так нужно смотреть в отладчике, я в нем всегда отлаживаю.
Точнее "только в скомпилированном виде". Я нашел почему:

Нет не поэтому, он не будет нормально работать в IDE даже если ты уберешь этот вызов. Поток не будет выполняться после ExitThread, пэтому падает не из-за этого.
Но так как альтернативы нет

viewtopic.php?f=15&t=39686&p=6723278
и есть еще куча функций по созданию потоков, но и там нет никакой инициализации.
Маршаллинг, что это? Почему, если он так важен, без него всё работает?

Что будет если вызвать метод объекта из двух разных потоков одновременно?
Julia. А чего это она не падает? Фэн-шуй?

Нет, там используется методы не требующие инициализацию рантайма.
UA6527P

Jack Ferre
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 132
Зарегистрирован: 17.02.2014 (Пн) 14:31
Откуда: Казахстан, Костанай

Re: Выход из потока. Планировщик.

Сообщение Jack Ferre » 27.07.2014 (Вс) 10:01

Много полезного узнал в этом топике. Однако нет комментариев по поводу планировщика.

ThreadSheduler.rar
(11.1 Кб) Скачиваний: 108


Что думаете о способе добавления/извлечения заданий из списка?
Пока сделал выполнение списка заданий по таймеру. Что скажете?

The trick
Постоялец
Постоялец
 
Сообщения: 781
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: Выход из потока. Планировщик.

Сообщение The trick » 27.07.2014 (Вс) 10:06

Ты можешь отправить окну асинхронное сообщение, можешь выставить эвент или любой другой семафор и его обработать в другом потоке.
UA6527P

Jack Ferre
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 132
Зарегистрирован: 17.02.2014 (Пн) 14:31
Откуда: Казахстан, Костанай

Re: Выход из потока. Планировщик.

Сообщение Jack Ferre » 28.07.2014 (Пн) 7:35

Я старался... придумывал... :|

Пиреписал исходник:
ThreadRedirect.rar
(11.99 Кб) Скачиваний: 117


Результат:
10000.png
10000.png (1.37 Кб) Просмотров: 3984


Sehr gut!


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

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

Сейчас этот форум просматривают: AhrefsBot и гости: 48

    TopList