Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по Delphi (до версии 2009) - часть 5

Модерирует : ShIvADeSt

ShIvADeSt (19-05-2010 05:14): Продолжаем тут http://forum.ru-board.com/topic.cgi?forum=33&topic=11215  Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

   

ShIvADeSt



Moderator
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Продолжение темы Вопросы по Delphi (до версии 2009) - часть 4

Познаем сами, помогаем другим...
Обсуждаем вопросы, не связанные с юникоидными версиями Delphi - для этого есть соответствующая тема (см. ссылки ниже).

Правила топика:
    Прежде чем спрашивать:
  1. Желательно изучить вопрос, попытаться найти ответ в прилагаемых мануалах, хелпах и анализируя исходники.
  2. Выполнить поиск по топику (открыть "Версия для печати" и поискать ответ там).
  3. Применить фильтр по разделу "Прикладное программирование". Ответы на многие старые вопросы могли быть даны в отдельных темах.
  4. Продумайте вопрос. На поверхностные вопросы вы получите поверхностные ответы, или вообще ответов не получите.
  5. Желательно указывать версии используемого компилятора и операционной системы.
    Прежде чем отвечать:
  1. Если не можете помочь, не мешайте.
  2. Если уж вы отвечаете на вопрос, давайте ответ по сути.
  3. Если вы не уверены, так и говорите! Ошибочный, но авторитетно звучащий ответ хуже, чем отсутствие ответа.
  4. Задавайте дополнительные вопросы, чтобы получить больше информации.
  • Отсутствие ответа не равносильно игнорированию - иногда участники форума просто не знают ответ. Повторная посылка вопроса не приветствуется. Посты типа "неужели никто не знает ответа..." или "может мне все-таки кто-нибудь ответит" недопустимы.  
  • Все большие куски кода (более 5 строк) оформляем в тег [morе] дабы уменьшить размер поста. FAQ по тегу [morе].

  • Всего записей: 3956 | Зарегистр. 29-07-2003 | Отправлено: 02:09 28-06-2009 | Исправлено: psa1974, 12:00 02-02-2010
    volser

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    DmitryKz
    На что ругается?

    Всего записей: 713 | Зарегистр. 31-03-2006 | Отправлено: 15:46 06-11-2009
    psa1974



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    volser
    там в примере, приведенном DmitryKz неверно объявлены многие локальные переменные, например htkThread, cbTokenGroups... Тип PTOKEN_GROUPS = TOKEN_GROUPS^; это что это за оно? в Windows.pas есть нормальное объявление этого типа , только называется он PTokenGroups... Ну и дальше по тексту...
     
    Свой вариант, в предыдущем посте я проверил, работает.

    Всего записей: 438 | Зарегистр. 08-11-2005 | Отправлено: 15:58 06-11-2009
    DmitryKz

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    psa1974
    Спасибо, будем посмотреть)
     
    volser
    Начиная с определения типа:
    type  
      PTOKEN_GROUPS = TOKEN_GROUPS^; здесь говорит, что ожидается ; а стоит ^
    затем на недекларированные идентификаторы: SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS
    и в этом коде:
    while iGroup < ptg^.GroupCount do // check administrator group
      begin
        if EqualSid(ptg^.Groups[iGroup].Sid, psidAdmin) then
    на GroupCount и Groups
     
     
    Добавлено:
    psa1974
    Пока писал свой ответ, Вы все разъяснили, спасибо.

    Всего записей: 3142 | Зарегистр. 29-09-2005 | Отправлено: 16:00 06-11-2009
    data man



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    psa1974
    Может выдаваться неправильный результат из-за маленького размера буфера под группы.
    Сначала бы определить размер буфера:

    Код:
    GetTokenInformation(hAccessToken, TokenGroups, nil, 0, dwInfoBufferSize);
    GetMem(ptgGroups, dwInfoBufferSize);



    ----------
    Любой достаточно развитый тролль неотличим от подлинно помешанного на какой-либо идее.
    Кекс. Антибиотики. Ламбада.

    Всего записей: 1696 | Зарегистр. 13-10-2005 | Отправлено: 16:13 06-11-2009
    psa1974



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    data man

    Цитата:
    GetTokenInformation(hAccessToken, TokenGroups, nil, 0, dwInfoBufferSize);

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

    Всего записей: 438 | Зарегистр. 08-11-2005 | Отправлено: 16:23 06-11-2009 | Исправлено: psa1974, 16:24 06-11-2009
    DmitryKz

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Ребята, помогите с такое проблемой:
    моя программа использует некий блок данных; первоначально он находится в 7zip архиве, в сжатом виде, со своим расширением, и будет доступен для скачивания из Интернета (сейчас этот блок данных в архиве занимает 17 мб, в разархивированном виде (около 200 файлов - 125 мегабайт, самый большой файл - БД, объемом 101 Мб). Этот архив в то же время своего рода инсталлятор - то есть по двойном клике он устанавливается в программу. А точнее говоря - перегоняется в Single File System без компрессии, но с шифрованием, и служит своего рода контейнером, куда программа обращается за данными. Просто мне так удобнее - это пока еще 200 файлов, а дальше будет больше. Но удручает время перегонки - около 3-х минут.
    Вот код:

    Код:
            with CreateInArchive(CLSID_CFormat7z) do
              begin
                SFS_File:=TSingleFileSystem.Create('c:\sfs.bkp', fmCreate);
                OpenFile(fn); //открываем 7-zip архив
                for i:=0 to NumberOfItems-1 do
                  begin
                      mstr:=TMemoryStream.Create;
                      SFS_Stream:=TSFSFileStream.Create(SFS_File, ItemPath[i], fmCreate);
                      ExtractItem(i, mstr, false); //Извлечение файла из 7зип архива в TMemoryStream;
                      SFS_Stream.LoadFromStream(mstr);
                      FreeAndNil(mstr);
                      FreeAndNil(SFS_Stream);
                  end;
              end;

    Можно ли тут что-то сделать? Забавно то, что если в прилагаемом SFS Manager упаковка в SFS проходит довольно скоро - секунд 5-6. Тут же, как я понимаю, почти все время тратится на создание и убийство потоков.
     
    Небольшие добавления:
    забыл еще добавить, что просто упаковка в SFS папки с моими 200-ми файлами тоже довольно быстра: около 8-10 секунд. Получается, что TMemoryStream тормозит?
    Я, конечно, могу распаковывать из 7-zip архива в папку и из нее упаковывать в SFS, но не хотелось бы мусорить в файловой системе и убирать за собой. Кроме того, содержимое этих данных, скажем так, защищено авторским правом (не моим ) и хотелось бы убрать эту лазейку к доступу к ним.

    Всего записей: 3142 | Зарегистр. 29-09-2005 | Отправлено: 00:00 07-11-2009 | Исправлено: DmitryKz, 10:20 07-11-2009
    psa1974



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    DmitryKz

    Цитата:
    Получается, что TMemoryStream тормозит?

    Ниже простой тест потоков. Файл Test0.exe взято на угад и весит 64 514 590 байт. Дык вот время выполнения цикла - 20 сек:

    Код:
     
    procedure TForm9.Button1Click(Sender: TObject);
    var
      mstr: TMemoryStream;
      i: Integer;
      Dat: TDateTime;
    begin
      Dat:= Now;
      for I := 0 to 199 do
      begin
        mstr:= TMemoryStream.Create;
        mstr.LoadFromFile('t:\TEMP\Test0.exe');
        mstr.Free;
      end;
      Label1.Caption:= TimeToStr(Now - Dat);
    end;
     

     
    Второй тест потоков. Взят тот же самый файл Test0.exe. В цикле гружу в поток файл и сохраняю поток в новый файл, после чего исходный файл прибиваю. Время выполнения цикла - 03:35, так это ж уже, извините, дисковые операции, само собой время расходуется:

    Код:
     
    procedure TForm9.Button1Click(Sender: TObject);
    var
      mstr: TMemoryStream;
      i: Integer;
      Dat: TDateTime;
      FileName: string;
    begin
      Dat:= Now;
      FileName:= 't:\TEMP\Test0.exe';
      for I := 0 to 199 do
      begin
        mstr:= TMemoryStream.Create;
        mstr.LoadFromFile(FileName);
        mstr.Position:= 0;
        FileName:= 't:\TEMP\Test'+ IntToStr(i+1)+'.exe';
        mstr.SaveToFile(FileName);
        mstr.Free;
        DeleteFile('t:\TEMP\Test'+ IntToStr(i)+'.exe');
      end;
      Label1.Caption:= TimeToStr(Now - Dat);
    end;
     

    Ну и третий тест Взят тот же самый файл Test0.exe. В цикле гружу в поток файл, потом из этого потока загружаю в другой поток, предварительно его очистив от предыдущего содержимого (операции чисто в памяти). Это практически то же самое что и у вас за исключением операций распаковки и манипулирования SFS папками. Время выполнения - 37 сек.

    Код:
     
    procedure TForm9.Button1Click(Sender: TObject);
    var
      mstr, mstr2: TMemoryStream;
      i: Integer;
      Dat: TDateTime;
      FileName: string;
    begin
      Dat:= Now;
      FileName:= 't:\TEMP\Test0.exe';
      mstr2:= TMemoryStream.Create;
      for I := 0 to 199 do
      begin
        mstr:= TMemoryStream.Create;
        mstr.LoadFromFile(FileName);
        mstr.Position:= 0;
        mstr2.Clear;
        mstr2.LoadFromStream(mstr);
        mstr.Free;
      end;
      mstr2.Free;
      Label1.Caption:= TimeToStr(Now - Dat);
    end;
     

    Не знаю, насколько мои тесты показательны, и где загвоздка, но мне здается, дело не в самом объекте TMemoryStream, а в методе SFS_Stream.LoadFromStream(mstr), т.е. у SFS_Stream какой-то тормоз включен...

    Всего записей: 438 | Зарегистр. 08-11-2005 | Отправлено: 13:59 07-11-2009
    ppkp

    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Подскажите, как из одного модуля(компонент), в котором есть программа с долгим вычислением передать значение для ProgressBar ? Пишу так
     
    unit Calc;
    const
      WM_MYPROCESS = WM_USER + 100;
    ...
     
    for I:=0 to 100000000000000000000 do begin
    // Здесь пробовал SendMessage и пр.
      PostMessage(HWND_BROADCAST, WM_MYPROCESS, WPARAM(I), 0);
    (Можно, конечно
      MainForm.ProgressBar.Position := I;
    но не хотелось бы, чтобы в компоненте была ссылка на Main)
    end;
     
    -----------------
    unit Main;
     procedure CMDProcess(var Message: TMessage); message WM_MYPROCESS;
     
    procedure TMainForm.CMDProcess(var Message: TMessage);
    begin
      ProgressBar.Position := Message.WParam;
    end;
     
    А в CMDProcess не попадает никогда. Почему?

    Всего записей: 480 | Зарегистр. 13-04-2006 | Отправлено: 17:09 07-11-2009 | Исправлено: ppkp, 17:10 07-11-2009
    VitaliM



    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    ppkp
    Ну поставил ты сообщение в очередь, а надо чтобы кто-то начал быстренько обрабатывать эту очередь. Постаь после PostMessage вызов Application.ProcessMessages и должно заработать.

    Всего записей: 2182 | Зарегистр. 12-01-2005 | Отправлено: 17:22 07-11-2009
    ppkp

    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Application.ProcessMessages стоит в главной (вызывающей) программе, а в компоненте-то зачем его ставить ?
    ЗЫ Не помогло это. Похоже, в компоненте нужно Handle вызывающей пр-мы вместо HWND_BROADCAST передавать в PostMessage. Но как его узнать?

    Всего записей: 480 | Зарегистр. 13-04-2006 | Отправлено: 18:33 07-11-2009 | Исправлено: ppkp, 18:57 07-11-2009
    VitaliM



    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

    Цитата:
    Application.ProcessMessages стоит в главной (вызывающей) программе

    ну пока идет цикл, Application.ProcessMessages не вызывается, значит некому обрабатывать очередь сообщений.

    Всего записей: 2182 | Зарегистр. 12-01-2005 | Отправлено: 18:51 07-11-2009
    ppkp

    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Дык, он вызывается перед началом цикла в главной программе !
     
    Application.ProcessMessages;
    CallMyComponentProc;//отсюда он попадает в цикл
     
    Почему не попадает в CMDProcess?
     
    Добавлено:
    Поставил
    SendMessage(MainForm.Handle, WM_PROCESS, WPARAM(row), 0);
    и все работает. Как и было. Как же мне не привязываться к Main ?

    Всего записей: 480 | Зарегистр. 13-04-2006 | Отправлено: 19:00 07-11-2009 | Исправлено: ppkp, 19:05 07-11-2009
    Odysseos



    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    ppkp
     
    Если это длительное вычисление производится в том же потоке, что и остальная программа - зачем там вообще сообщениями пользоваться? Просто добавить в список параметров CallMyComponentProc ProgressBar: TProgressBar, и передавать туда нужный ProgressBar. Только не забыть раз в сколько-то проходов по циклу вызывать Application.ProcessMessages().

    Всего записей: 186 | Зарегистр. 02-01-2006 | Отправлено: 19:40 07-11-2009 | Исправлено: Odysseos, 19:44 07-11-2009
    ppkp

    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Тогда и получается, что не привязанный к форме компонент написать нельзя. Ведь для того, чтобы строка
    ProgressBar: TProgressBar
    компилировалась, нужно в компоненте писать uses MainUnit. Какая здесь независимость от формы?

    Всего записей: 480 | Зарегистр. 13-04-2006 | Отправлено: 19:52 07-11-2009
    DmitryKz

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    psa1974
    Ну вот пошел по пути распаковки 7зип архива в папку и упаковки из папки в SFS - 10 секунд. Дисковые операции, однако

    Всего записей: 3142 | Зарегистр. 29-09-2005 | Отправлено: 19:59 07-11-2009 | Исправлено: DmitryKz, 19:59 07-11-2009
    psa1974



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    ppkp
    Насчет компонента. А что мешает воспользоваться стандартной практикой и реализовать в компоненте событие, скажем OnProgress, а в форме, где используешь этот компонент - написать обработчик события? Имхо, зачем придумывать лисапед, когда уже все давно придумано.
     
    Но если все же надо через сообщения...

    Цитата:
    Application.ProcessMessages стоит в главной (вызывающей) программе, а в компоненте-то зачем его ставить ?

    Затем, что в компоненте любые методы в конечном счете отрабатывают, как реакция на то или иное событие. И если на какое-то событие реакция весьма длительна (скажем твой цикл),  то само собой, никакие другие сообщения не выбираются из очереди и не обрабатываются, пока не закончится обработка этого текущего сообщения, как следствие, твоя форма физически не получает твоего сообщения, пока не закончится цикл.
    Весь смысл метода Application.ProcessMessages - организовать локальный цикл выборки сообщений. Т.е., на пальцах: в текущий момент времени выбрать из очереди сообщений накопившиеся там сообщения и обработать. Всё. Смысл его вызывать перед началом цикла в главной программе??? Когда у тебя работает цикл, то, опять же  , на пальцах, пока этот цикл не закончится, никакие сообщения из очереди сообщений не выбираются и не обрабатываются. Application.ProcessMessages надо вызывать не перед и не после, а ИМЕННО В ЦИКЛЕ! Тогда при каждом вызове Application.ProcessMessages выполнение цикла приостановится, сообщения из очереди выберутся и обработаются, после чего цикл продолжится.
     
    DmitryKz
    Учитывая что у вас на данный момент 200 файлов общим распакованным размером 125 мб при использовании TMemoryStream обрабатывалось 3 минуты, а в моем тесте 200 файлов по 62 мб, т.е. общим объемом 12305 мб (или 12 гб) обрабатывалось в течение 3-х с половиной минут ...

    Всего записей: 438 | Зарегистр. 08-11-2005 | Отправлено: 20:24 07-11-2009 | Исправлено: psa1974, 20:30 07-11-2009
    ppkp

    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Попробовал через создание обработчика OnBlaBlaBla - заработало. Давно надо было додуматься. Большое спасибо.
     
    А Application.ProcessMessages я все время использовал перед большим циклом и в основной программе - для освобождения мыши и прочих ресурсов - и все нормально. Но тогда мне не нужно было получать значение из цикла. И, насколько я рыл по компонентам, нигде не видел этого вызова. ИМХО. И сейчас я его вызвал не из цикла в компоненте, а в обрабочике из главной программы.
     
    Спасибо большое еще раз.

    Всего записей: 480 | Зарегистр. 13-04-2006 | Отправлено: 21:42 07-11-2009 | Исправлено: ppkp, 21:54 07-11-2009
    DmitryKz

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    psa1974
    Да убедили-убедили конечно...
    Просто теряюсь в догадках, но тоже склоняюсь к выводу насчет
    Цитата:
    SFS_Stream.LoadFromStream(mstr), т.е. у SFS_Stream какой-то тормоз включен...


    Всего записей: 3142 | Зарегистр. 29-09-2005 | Отправлено: 22:24 07-11-2009
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    DmitryKz
    Может профилировщиком его?
    ppkp
    Отличная статья на тему сообщений: http://delphikingdom.com/asp/viewitem.asp?catalogid=169

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 22:42 07-11-2009
    TechnoDreamer

    Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Такая проблема, есть TTrackBar, максимальное значение на нем большое (тысячи), шаг 1. Значение можно выбрать перетягивая ползунок, но это не совсем удобно для пользователя. Хотелось бы что бы он кликнув куда то сразу поменял позицию на то место (типа как перемотка в медиаплеерах). Можно это как то реализовать используя данный компонент (TProgressBar тоже бы подошел, бегунок не так важен как возможность выбрать позицию одним кликом), или возможно какие то сторонние компоненты...

    Всего записей: 259 | Зарегистр. 01-06-2008 | Отправлено: 04:29 08-11-2009
       

    Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

    Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по Delphi (до версии 2009) - часть 5
    ShIvADeSt (19-05-2010 05:14): Продолжаем тут http://forum.ru-board.com/topic.cgi?forum=33&topic=11215


    Реклама на форуме Ru.Board.

    Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
    Modified by Ru.B0ard
    © Ru.B0ard 2000-2024

    BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

    Рейтинг.ru