Что нового

[Интеракция] Зависает GUI на время работы dll

Vova93

Новичок
Сообщения
8
Репутация
0
из скрипта с GUI вызывантся функция из моей dll, которая работает продолжительное время и периодически вызывает callback функцию в скрипте для передачи данных. callback функция некоторое время успешно обновляет данные в окне (но оно уже ни на что не реагирует). Но потом графический интерфейс окончательно зависает, и становится активным только уже после окончания работы самой dll. Можно ли этого избежать не запуская другую копию скрипта?
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Re: [Интеракция] Обмен данными между скриптом и длительно работающей dll

Можно вызывать через

Код:
AdlibRegister()


если dll самописная, то в ней можно создать поток в котором будет работать сама функция, а в скрипте просто стартовать этот поток
 
Автор
V

Vova93

Новичок
Сообщения
8
Репутация
0
в скрипте просто стартовать этот поток
Дело в том, что dllcall будет по любому держать скрипт, пока dll сама полностью не завершит работу.
AdlibRegister() не подойдёт, так как dll производит вычисления, которые придёстя прерывать каждые 500 1000 мс,последний результат возвращать, а потом снова вызывать dll, передавать последний результат для продолжения ....
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Не будет, для этого я и говорю чтоб в dll реализовать поток, на чём dll писана и что именно делает функция из dll? Если не хотите переписывать, то воспользуйтесь функцией AdlibRegister, она позволяет выполнять часть кода не прерывая работы основного кода.
 
Автор
V

Vova93

Новичок
Сообщения
8
Репутация
0
dll написана на C++. Она находит минимальный полином Жегалкина неявно заданной булевой функции от эн переменных. Кол-во построенных полиномов в данный момент она и должна возвращать в основной скрипт.
Что касается AdlibRegister, то в документации написано "Adlib-функция должна оставаться предельно простой, поскольку вызывается часто (а работа основного скрипта приостанавливается)"
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Можно ещё таймер задействовать

Код:
#Include <WindowsConstants.au3>
#Include <GUIConstantsEx.au3>

$hForm = GUICreate('', 200, 200)
$iButton = GUICtrlCreateButton('click', 20, 20, 80, 25)
GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_TIMER, 'WM_TIMER')

DllCall('User32.dll', 'int', 'SetTimer', 'hwnd', $hForm, 'int', 1, 'int', 100, 'int', 0)


While 1
    Switch GUIGetMsg()
        Case -3
            Exit
		Case $iButton
            MsgBox(0, '', '')
    EndSwitch
WEnd

Func WM_TIMER($hWnd, $Msg, $wParam, $lParam)
	Local Static $iNumb = 0

    Switch $Msg
        Case $WM_TIMER
            If ($iNumb > 1000) Then
		        $iNumb = 0
	        EndIf
	        WinSetTitle($hWnd, '', $iNumb)
	        $iNumb += 1
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc
 
Автор
V

Vova93

Новичок
Сообщения
8
Репутация
0
Можно ещё таймер задействовать
Попробовал. DllCall (моя) намертво вешает скрипт, совсем не так как открытый MsgBox или диалог выбора файла.
А если я сделаю дополнительный поток в Dll, основной поток же никуда не денется, и скрипт всё равно будет ждать его завершения?
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Потоки, они для того и потоки, чтобы выполнять одну часть кода и не мешать другой.
 
Автор
V

Vova93

Новичок
Сообщения
8
Репутация
0
Это понятно. Но сначала же запускается основной поток, который контролирует все остальные, и пока они не отработают, основной поток не завершится, и скрипт будет ждать его.
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Честно говоря я мало знаю про потоки, но не большой опыт с ними был в языке PureBasic, создавал 3 потока, при закрытии окна, все потоки завершались автоматически и ни чего ждать не нужно было.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Этот баг с GUI и меня напрягает. Уже думал сделал его прорисовку в новом EXE.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
inververs сказал(а):
Этот баг с GUI и меня напрягает.
В чем баг? AutoIt НЕ поддерживает работу с потоками. И, естественно, никакой AdlibRegister() и прочие танцы с бубном не избавят от зависания AutoIt части кода на время выполнения функций из DLL.

@Vova93

Если DLL ваш, то создайте внутри отдельный поток, в котором и будут производиться все необходимые вычисления. Но это все равно не позволит вам нормально организовать callback функцию в AutoIt (будет работать только в одном потоке). Поэтому рекомендую вместо callback функции создать структуру, в которую функция из DLL будет помещать необходимую информацию. AutoIt же в свою очередь будет считывать данные из этой структуры (в цикле или с помощью того же AdlibRegister()). Если DLL не ваш, то напишите отдельный DLL-обертку, который будет создавать поток, вызывать функцию вычисления из основной DLL и записывать данные в структуру. Это будет своего рода прослойка между основной DLL и AutoIt.
 
Автор
V

Vova93

Новичок
Сообщения
8
Репутация
0
Autoit однопоточный, но почему-то такие функции как playsound и InetGet могут работать параллельно коду. Что мешало разработчикам зделать и dllcall таковой, я не знаю. Но это еще полбеды. Например, та же msgbox тоже вроде как останавливает выполнение кода, но если у нас есть GUI, то он всегда остается полностью активным (можно кликать меню, чекбоксы, набирать в input полях). В то время, как dllcall полностью вешает интерфейс, в заголовке окна появляется надпись "Не отвечает" и оно уже ни на что не реагирует! А так можно было бы через callback мониторить контролы.
Что касается dll, то мне так и не удалось передать потоку в качестве параметра структуру:
Код:
typedef struct arglist
	{
		byte* VAL;
		bool* coef;
		ULONG* control;
		ULONG tr;
		ULONG row;
	}arglist;
Все найденные мною примеры не рабочие (по крайней мере в Visual studio 2010). Может кто подскажет?


Добавлено:
Сообщение автоматически объединено:

Спасибо. Разобрался. Создание другого потока помогло. А структуру просто сделал глобальной и никаких параметров не передавал.
 
Верх