FreeBasic
Главная
Вход
Регистрация
Пятница, 19.04.2024, 03:45Приветствую Вас Гость | RSS
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » Freebasic » Вопросы по языку FreeBasic » Потоки в dll (Почему потоки "пересекаются"?)
Потоки в dll
WQДата: Воскресенье, 04.05.2014, 12:27 | Сообщение # 1
Полковник
Группа: Проверенные
Сообщений: 215
Репутация: 7
Статус: Offline
Недавно познакомился с FreeBasic.
Создаю dll, которую будет вызывать внешняя программа.
Задача dll - в разных потоках независимо рисовать текст с помощью gdip+ и показывать картинки в ImageGadget.

Однако при вызове функции загрузки картинки рисование текста притормаживает.

Не могу понять, дело в неправильном алгоритме, или это глобальное ограничение языка?

Пример:
 
haavДата: Воскресенье, 04.05.2014, 14:52 | Сообщение # 2
Генералиссимус
Группа: Администраторы
Сообщений: 1361
Репутация: 49
Статус: Offline
Начну с того, что не касается проблемы:

Советую заглянуть в файл:

#Include "window9.bi"

То есть первое , что не нужно в коде:

Код
'#Include "windows.bi"
'#Include "win/gdiplus.bi"


просто потому, что оно уже включено.

Ну а теперь сама проблема:

1) Интерфейс GUI рекомендуется создавать в одном основном потоке, потому что я уже не раз сталкивался с тем, что многие сообщения просто не дойдут до окна, созданного в другом потоке. Отсюда все окошки правильно создавать в основном потоке

2) Даже если наплевать на 1 пункт, то в первую очередь нужно понять, что создавая отдельные потоки, обязательно нужно заботиться о безопасности доступа к данным в программе. В коде же предложенном выше я вижу сплошные ошибки. Окна создаются в разных потоках, но обработка сообщений в одной процедуре. Или переменная S1B одна на все потоки без мьютексов, получается что несколько потоков в определенный момент обращаются к данным одновременно, что вполне закономерно вызовет не только тормоза, но вылеты программы. Представим себе разные потоки как 3-4 человека, которые зашивают одну разорванную рубашку. Пока все шьют в разных местах, все нормально, но вот они дошли до места, где каждый из них пытается иголкой попадать в одно место и в одно время, что будет?

Мой совет:

1) как следует изучить управление потоками (хотя бы прочитать и понять это)
2) определить места в программе , где без потоков никак не обойтись, все остальные места сделать в основном потоке. Неправильно пихать эту технику во все дыры. В одной из моих программ без потоков никак не обойтись, мне пришлось их создать 2 или 3. И даже с этим малым кол-вом потоков я испытал настоящий напряг с обработкой общих данных.

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


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
WQДата: Воскресенье, 04.05.2014, 16:35 | Сообщение # 3
Полковник
Группа: Проверенные
Сообщений: 215
Репутация: 7
Статус: Offline
haav
Спасибо за оперативный ответ!

Цитата
1) как следует изучить управление потоками (хотя бы прочитать и понять это)

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

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

Я пишу программу на языке autoit, и хочу расширить ее функционал с помощью dll, написанных на FreeBasic, т.к. в autoit нет многопоточности.
Все делается в одном цикле, и рисование gdip-функциями притормаживает, если добавить в цикл еще какое-нибудь действие, вроде загрузки картинки.

Здесь http://rusfolder.com/40606631
архив с примером autoit-программы - clo.exe

Что она делает - при запуске нужно указать папку с jpg, и программа покажет 3 окна: 1 свое, autoit-кое, и 2 - вызванные из dll FreeBasic, одно окно - движущийся текст, а другое - для показа картинок в ImageGadget
Если нажимать клавишу "Pause", скрипт autoit вызывает функцию из dll для переключения картинок в ImageGadget, картинки переключаются.
Но проблема в том, что при этом текст начинает двигаться рывками.

Задача - сделать, чтобы и картинки грузились, и тормозов текста не было.


Сообщение отредактировал WQ - Воскресенье, 04.05.2014, 16:43
 
haavДата: Воскресенье, 04.05.2014, 19:41 | Сообщение # 4
Генералиссимус
Группа: Администраторы
Сообщений: 1361
Репутация: 49
Статус: Offline
Вот так не пойдет?

Код
#Include "window9.bi"
Using GDIPLUS
Dim Shared As String sPath(100) ' список путей к файлам изображений.

Function LoadImageWindow() As hwnd Export
  Var hwnd = OpenWindow("ImageAnimate",10,10,600,600)
  ImageGadget(1,10,10,580,580)
  Return hwnd
End Function

Function LoadTextWindow() As hwnd Export
  Var hwnd = OpenWindow("TextAnimate",10,10,200,200)
  ImageGadget(2,10,10,180,180)
  Return hwnd
End Function

Sub AnimateText(sText As ZString Ptr) Export
  Static As Integer y = 10,x = 0
  Do
   WindowStartDrawA(GadgetID(2))
   BoxDrawA(0,0,200,200,&hfff0f0f0,,&hfff0f0f0)
   ModeDrawA(2)
   TextDrawA(*sText,x,y,,&h80FF0000,,TextRenderingHintAntiAlias)
   StopDrawA
   x+=2
   If x>200 Then x = 0
   If WindowEvent = eventclose Then End
   Sleep(10)
  Loop

End Sub

Sub AnimateImage(Directory As ZString Ptr) Export
  Dim As Integer i
  Var Dir_=ExamineDirectory(*Directory, "*.bmp*")
  Do
   sPath(i) = *Directory & DirectoryEntryName(Dir_)
   i+=1
  Loop While NextDirectoryEntry(Dir_)

  For j As Integer = 0 To i-1
   Var hbitmap=Load_image(sPath(j))
   hbitmap=Resize_image(hbitmap,500,500)
   SetImageGadget(1,hbitmap)
   Free_Image(hBitmap)
   If WindowEvent = eventclose Then End
   Sleep(500)
  Next
    DisableGadget(100,0)
End Sub

CenterWindow(OpenWindow("main",10,10,200,200))
ButtonGadget(100,10,10,100,20,"запуск анимации картинок")

LoadImageWindow()
LoadTextWindow()
ThreadCreate(Cast(Any Ptr,@AnimateText), @"freebasic")

Do
  Var ev = WaitEvent
  Select Case ev
   Case eventclose
    End
   Case eventgadget
    If EventNumber = 100 Then
     ThreadCreate(Cast(Any Ptr,@AnimateImage), @"D:\OBOI\")
     disableGadget(100,1)
    EndIf
  End Select   
Loop


Для путей я брал свой каталог с файлами bmp. Данный код просто для теста без использования autoIt . Только средствами FB. Но если он работает нормально, то переписать (обернуть в функции) часть кода не будет сложным. Я сделал с 2 потоками.


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
WQДата: Понедельник, 05.05.2014, 12:08 | Сообщение # 5
Полковник
Группа: Проверенные
Сообщений: 215
Репутация: 7
Статус: Offline
haav
Спасибо за пример!

К сожалению, если картинки формата jpg или png, то рывки у текста все равно наблюдаются, с bmp вроде нормально. Но bmp несжатый формат, возможно дело в этом...

Еще в этой теме пожелание оставил http://freebasic.ucoz.com/forum/3-133-2


Сообщение отредактировал WQ - Понедельник, 05.05.2014, 12:23
 
haavДата: Понедельник, 05.05.2014, 17:10 | Сообщение # 6
Генералиссимус
Группа: Администраторы
Сообщений: 1361
Репутация: 49
Статус: Offline
Цитата WQ ()
К сожалению, если картинки формата jpg или png, то рывки у текста все равно наблюдаются, с bmp вроде нормально. Но bmp несжатый формат, возможно дело в этом...


Да, я попробовал на bmp больших размеров, есть тормоза. Я не знаю точно почему это возникает, у меня только смутные догадки.

1 догадка: Как не распараллеливай задачи, все равно вся отрисовка происходит в одних и тех же функциях DLL. То есть пока рисуется изображение на одном окне, отрисовка текста в другом окне встает в очередь и наоборот. GDI никогда не славилась скоростью. Стабильностью, совместимостью да, но только не скоростью.
2 догадка: Может влияет то, что файлы считываются постоянно с жесткого диска (все таки скорость обмена данными с хардом низкая).

Что можно сделать в этой ситуации. Я пока вижу только один выход( может их конечно несколько и есть более простые и более удобные, но я пока вижу только один). Сделать отрисовку разных окон разными графическими библиотеками. То есть, например текст и еще какую нибудь мелочевку в одном окне рисовать с помощью GDI+ , а изображения в другом окне с помощью того же встроенного FBGFX или с помощью OpenGL.



Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
WQДата: Понедельник, 05.05.2014, 23:44 | Сообщение # 7
Полковник
Группа: Проверенные
Сообщений: 215
Репутация: 7
Статус: Offline
Цитата haav ()
Да, я попробовал на bmp больших размеров, есть тормоза. Я не знаю точно почему это возникает, у меня только смутные догадки. 1 догадка: Как не распараллеливай задачи, все равно вся отрисовка происходит в одних и тех же функциях DLL. То есть пока рисуется изображение на одном окне, отрисовка текста в другом окне встает в очередь и наоборот. GDI никогда не славилась скоростью.

Я пока вижу только один выход( может их конечно несколько и есть более простые и более удобные, но я пока вижу только один). Сделать отрисовку разных окон разными графическими библиотеками. То есть, например текст и еще какую нибудь мелочевку в одном окне рисовать с помощью GDI+ , а изображения в другом окне с помощью того же встроенного FBGFX или с помощью OpenGL.

Действительно, похоже что все упирается в функцию Load_image, которая пересекается с рисованием. Плохо, этими функциями просто и удобно загружать и обрезать картинки.

В сборке Freebasic есть пример TestFBEPictViewLib.bas
Попробовал прикрутить показ картинок из него - вроде рисование работает без тормозов, но там мне непонятно, как указывать размер и положение этого самого элемента показывающего картинку + нужно размеры картинки подгонять. Смотрел библиотеки IUP и FLTK - там неплохие примеры с картинками, но пока не разобрался с документацией.
В общем, мне бы небольшой пример загрузки картинки в произвольное окошко какой-нибудь сторонней библиотекой, а дальше я сам разбираться буду.

В FLTK есть и рисование текста, вроде не хуже GDI. Вообще, опять же, неплохо бы заменить GDI на что-то с поддержкой аппаратного ускорения - мне нужно рисовать несколько окон с движущимся текстом, а это сильно нагружает процессор.
 
haavДата: Вторник, 06.05.2014, 07:02 | Сообщение # 8
Генералиссимус
Группа: Администраторы
Сообщений: 1361
Репутация: 49
Статус: Offline
Чтобы что-то советовать, надо четко понимать, что в конце концов нужно сделать. По прошлому примеру я видел, что надо создать одно окно для вывода изображений с жестко заданным размером и одно окно с текстом. Теперь оказывается надо несколько окон с текстом. Потом может быть окажется что и изображения надо рисовать с любыми размерами, а может быть и не в одном окне. Опять же я гадаю... изображения будут всегда одни и те же (в одной папке) , или это на выбор пользователя. Может быть вообще все удобнее\правильнее сделать в одном окне при помощи OpenGL или FbGfx... В общем пока нет четко установленной задачи , все что я советую (или буду советовать) , окажется малопродуктивным.

Цитата
Вообще, опять же, неплохо бы заменить GDI на что-то с поддержкой аппаратного ускорения - мне нужно рисовать несколько окон с движущимся текстом, а это сильно нагружает процессор.


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

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


Если тормоза именно из-за Load_image , то можно попробовать загрузку картинок с помощью freeimage (понимает кучу форматов), на моем сайте есть ссылка на архив. А с выводом на окна надо определяться с графическими библиотеками. Я могу ошибаться, но мне кажется что все библиотеки fltk, iup , cairo завязаны на GDI под windows. То есть наверняка эффект будет тот же.


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
WQДата: Среда, 07.05.2014, 12:26 | Сообщение # 9
Полковник
Группа: Проверенные
Сообщений: 215
Репутация: 7
Статус: Offline
В сборке Freebasic есть пример PictCtrl.Bas, а в нем функции LoadPict и BitmapFromPicture(на основе WinApi, как я понимаю).
Замена Load_image на LoadPict привела к получению нужного результата.
Правда, не читает png.
Freeimage не хочется использовать, т.к. с программой придется таскать и dll
 
Форум » Freebasic » Вопросы по языку FreeBasic » Потоки в dll (Почему потоки "пересекаются"?)
  • Страница 1 из 1
  • 1
Поиск: