Конференция "Media" » Мультимедиа таймер и вывод графики
 
  • Efir © (06.09.07 14:54) [0]
    При использовании таймера из модуля MMSystem, в котором идёт вывод битмапа, через некоторое время происходит коллапс.
    Т.е. если потаскать форму или изменять её размеры рисование битмапа не происходит.

    Вот примерный код:

    var
     bmp:TBitmap;
     TimerSpectrId:UINT;

    procedure Timer(uTimerlD, uMessage: UINT;dwUser, awl, dw2: DWORD);stdcall;
    begin
     bmp.Canvas.Brush.Color:=RGB(Random(256), Random(256), Random(256));
     bmp.Canvas.Rectangle(0,0,100,100);
     Form1.Canvas.Draw(0,0,bmp);
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
     bmp:=TBitmap.Create;
     bmp.Width:=100;
     bmp.Height:=100;

     TimerSpectrId:=timeSetEvent(50, 1, @Timer, 0, TIME_PERIODIC);
    end;
  • Dib@zol © (06.09.07 15:44) [1]
    Переименуй Timer, скажем в _Tmr0001, т.к. это там в ВЦЛ чего-то перекрывает, что возможно и является причиной.
  • Сергей М. © (06.09.07 16:01) [2]

    > Efir ©   (06.09.07 14:54)


    Мутьтимедийные таймеры работают в своих собственных дополнительных потоках, поэтому обращение к визуальным VCL-контролам в теле колбэк-процедуры Timer() недопустимо.
  • sdubaruhnul (06.09.07 16:23) [3]
    >Мутьтимедийные таймеры работают в своих собственных дополнительных потоках, поэтому обращение к визуальным VCL-контролам в теле колбэк-процедуры Timer() недопустимо.

    Т.к. у Delphi нет средств, чтобы это проконтроллировать и пресечь, это вполне допустимо.
  • Сергей М. © (06.09.07 16:36) [4]

    > у Delphi нет средств, чтобы это проконтроллировать


    Да ты что ?!
    А мужики-то и не знают)


    > и пресечь


    Зачем пресекать-то ?


    > это вполне допустимо


    Угу. Только потом не надо при всем честнОм народе жаловаться на "глюки" и "коллапсы")
  • sdubaruhnul (06.09.07 16:42) [5]
    >Угу. Только потом не надо при всем честнОм народе жаловаться на "глюки" и "коллапсы")

    Почему не надо? Надо. И требовать, чтобы потоки по-человечески сделали.

    Про зачем пресекать по инерции спросил?
  • Сергей М. © (06.09.07 16:47) [6]

    > требовать, чтобы потоки по-человечески сделали


    Не понял... Кто у кого требовать должен ? И что значит "по-человечески" ?


    > Про зачем пресекать по инерции спросил?


    Нет не по инерции.

    Зачем пресекать то что продумано разработчиком (в дан.случае разработчиками MS Windows) и очевидно ?
  • Efir © (06.09.07 16:56) [7]

    > Мутьтимедийные таймеры работают в своих собственных дополнительных
    > потоках, поэтому обращение к визуальным VCL-контролам в
    > теле колбэк-процедуры Timer() недопустимо.


    Но тогда почему проблемы возникают именно с битмапом, который я трогаю только из потока. Проблема исчезает при использовании Lock, UnLock.

    bmp.Canvas.Lock;
    bmp.Canvas.Brush.Color:=RGB(Random(256), Random(256), Random(256));
    bmp.Canvas.Rectangle(0,0,100,100);
    Form1.Canvas.Draw(0,0,bmp);
    bmp.Canvas.UnLock;
  • Сергей М. © (06.09.07 17:01) [8]

    > почему проблемы возникают именно с битмапом, который я трогаю
    > только из потока


    Это не очевидно.

    Зато очевидна засада в строчке

    Form1.Canvas.Draw(0,0,bmp);
  • sdubaruhnul (06.09.07 17:13) [9]
    >Не понял... Кто у кого требовать должен ? И что значит "по-человечески" ?

    Ты, я, Эфир, Дядя Фёдор, пёс и кот у КодеГеар. По-получеловечески значит хотя бы warning.
  • Сергей М. © (06.09.07 17:24) [10]

    > у КодеГеар


    Опять не понял)..

    Что мы должны требовать у "КодеГеар" ? Чтобы он переделал функциональность timeSetEvent что ли ?


    > хотя бы warning


    Кто кого о чем должен предупреждать ?
  • sdubaruhnul (06.09.07 17:29) [11]
    >Сергей М. ©   (06.09.07 17:24) [10]

    >TimerSpectrId:=timeSetEvent(50, 1, @Timer, 0, TIME_PERIODIC);

    Вот здесь компилятор Delphi должен возопить, что callback будет выполняться в другом потоке, поэтому весь код в нём должен быть thread-safe.
  • Efir © (06.09.07 17:30) [12]

    > Сергей М. ©


    Спасибо.
  • Сергей М. © (06.09.07 17:38) [13]

    > sdubaruhnul   (06.09.07 17:29) [11]


    > здесь компилятор Delphi должен возопить, что callback будет
    > выполняться в другом потоке


    С какого перепугу он должен "возопить" ?

    Для компилятора ф-ция timeSetEvent - точно такая же как и сотни и тысячи других подпрограмм, генерацию кода вызова которых ты от него требуешь.

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

    Так что не городи уже чушь)
  • sdubaruhnul (06.09.07 18:02) [14]
    >Компилятор знать не знает и знать не обязан о контексте работы вызванной подпрограммы, знать это положено нам как разработчикам прикладной логики. А знать это мы можем как минимум внимательно читая всякие мануалы и справки, где описывается логика работы той или иной интересующей нас п/программы.

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

    Раз уж компилятор не знает, то среда должна предоставить безопасное решение таймера, пускай на основе того же MMSystem'ного таймера (TTimer не есть такое решение). С этим у Delphi вообще туго.

    Так что не надо про чушь. Я читал много веток с твоим участием, про чушь ты любишь говорить. Так проще всего. Согласен, чуть-чуть дополнений ([7]) и всё работает и можно вроде бы не волноваться. Любые возражения - это чушь, потому что есть рабочий код. Пусть и в таком грязном стиле - функция API смешана с VCL. Но меня волнует стиль, и для меня это не чушь.

    И не надо отсылать ко всяким мануалам. Разве oxfff не показал, что даже оператор присвоения недокументировано не thread-safe?
  • Инс © (06.09.07 23:48) [15]

    > Так что не городи уже чушь)

    Двумя лапами поддержу. Чушь полнейшая. Среда ничего не обязана знать (да и не может), программист обязан перед использованием функции ознакомится с ее описанием в MSDN.
  • Сергей М. © (07.09.07 10:48) [16]

    > Если компилятор чего-то не знает, то он должен гарантировать
    > безопасное выполнение кода в любом возможном случае


    Ерунда полная.
    Пример ? Пожалуйста !

    В BASM-блоке кода ты вправе такого нахреновертить, что мало не покажется не то что компилятору, а и самой ОС.

    Вот как, скажи на милось, компилятор распознает опасность модификации того или иного сегментного регистра, если он сам дает тебе право его модифицировать, полагаясь на твои знания+разум и защищенность ОС от твоих неверных программных манипуляций ?


    > среда должна предоставить безопасное решение таймера


    Она и предоставляет. На основе того же TTimer. Но и с TTimer'oм при желании можно "наловить косяков".

    Касаемо же подобного  рода API-ф-ций среда полагается опять же на знания+разум программиста, предупреждая при этом о потоконебезопасности VCL.
  • sdubaruhnul (07.09.07 12:11) [17]
    >В BASM-блоке кода ты вправе такого нахреновертить, что мало не покажется не то что компилятору, а и самой ОС.

    Мы говорим о языке Delphi или о BASM? Кажется, код из [0] был написан на Delphi. Кстати, об ассемблерных вставках недавно была ветка, где я выразил мнение о том, что их надо вообще запретить. Причина? Именно потому, что в ней "ты вправе такого нахреновертить, что мало не покажется не то что компилятору, а и самой ОС".

    Теперь мой пример. Range checking. Или ты скажешь, что это тоже чушь? Что программист должен всегда проверять индекс в коде, а если пропустил, то искать непонятную AV? Кажется, есть такой язык - C - где проверки границ нет. И какова его область применения сейчас?
  • Rial © (07.09.07 20:09) [18]
    > [17] sdubaruhnul   (07.09.07 12:11)

    Плохая примета после грибочков писать на форуме. ^^

    Запретить BASM? Ну извините, это мое дело, использовать его
    или нет. Если ты не в состоянии предугадать, какие неожиданности
    будут в результате выполнения того или иного кода - это
    твои проблемы как программиста, а не бедной среды, которая
    тебе так не угодила.

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

    Вообще, ты и правда несешь чушь. Если что-то не получается
    сделать - это не повод тут же пинять на среду, компилятор
    и всех, под руку попавшхся.

    > [0] Efir ©   (06.09.07 14:54)

    Покопай в сторону синхронизации между потоками.
    Введи эти слова в поске и тут же найдешь много интересного.
  • sdubaruhnul (07.09.07 21:43) [19]
    >Запретить BASM? Ну извините, это мое дело, использовать его
    или нет. Если ты не в состоянии предугадать, какие неожиданности
    будут в результате выполнения того или иного кода - это
    твои проблемы как программиста, а не бедной среды, которая
    тебе так не угодила.


    Очень показательно здесь слово "предугадать". Угадывай на здоровье.

    Нафига нам BASM, об который спотыкается оптимизатор?

    >По поводу таймера. А если я напишу свой таймер, который будет
    выполняться в отдельном потоке, то как теперь несчастный
    компилятор должен выдавать предупреждения?


    Вот, в этом то весь вопрос. Ты не можешь себе представить, как это можешь быть осуществлено. Какие средства языка нужны для этого. Ты просто представляешь себе перед глазами работу потоков в Delphi и не понимаешь, куда там можно впихнуть проверку.

    Просто для того, чтобы ты мог хоть немного пофантазировать, приведу простой пример из другого языка - Java. Если в каком-то методе может возникать исключение, то это указывается в объявлении метода после ключевого слова throws, и программа не откомпилируется, пока у этого исключения не будет обработчика.

    Если ты удовлетворяешь требованиям, которые ты же с Сергеем М установил (про логическое мышление программиста), то сможешь расширить этот пример и до дельфийских потоков. И также вспомнишь, что подобные примеры есть даже в Делфи, причём довольно старые и успешные.
 
Конференция "Media" » Мультимедиа таймер и вывод графики
Есть новые Нет новых   [134431   +15][b:0][p:0.001]