Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi 2

Автор: Arvur
Дата сообщения: 12.10.2006 19:13
webgirlhb
Ммм... Попробуй в OnShow засунуть. И проверь у формы свойство OldCreateOrder.
Автор: webgirlhb
Дата сообщения: 13.10.2006 07:13
Большое всем спасибо за ответы, с ошибкой разобралась
Почему-то помогло обращение к форме не по имени, а через переменную Self:
... if Self.Components[i] is TRzDBCHECKBoxEnable then ...
Автор: vserd
Дата сообщения: 13.10.2006 09:33
RomanTim

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

К тому же уйдя от TTread при работе из дочернего потока с визуальными компонентами сразу приходишь к необходимости самостоятельно реализовывать Synchronize - не смертельно конечно, но зачем?

По условиям моей задачи нужно было запускать до трех-пяти потоков. Выполнять нектороые действия. Если делать это через TThread тогда приходилось делать множество телодвижений, которые по моему мнению были излишни. Когда сделал тоже самое через класс, вопервых сократился объем кода, и удалось уйти от бесполезных телодвижений. Так что в моих условиях это было плюсом или двумя плюсами :)))
Работать из потока с визуальными компонентами, IMHO, является злом.
Автор: Arvur
Дата сообщения: 13.10.2006 13:43
vserd

Цитата:
передавать ему метод класса в качестве потоковой функции

Интересная тема... Можешь проиллюстрировать примером кода?
Автор: RomanTim
Дата сообщения: 13.10.2006 13:43
vserd
Ну значит есть задачи где это помогает - у меня вроде все, что сделано в потоках, на TThread хорошо ложится
А зло или нет обращаться к визуальным компонентам - тоже все зависит от задачи. Бывают варианты когда не достаточно PostMessage

Arvur

Цитата:
Интересная тема... Можешь проиллюстрировать примером кода?

Все просто - заводишь функцию класса такого вида какой ждет CreateThread и передаешь на нее указатель
[more=Вот простенький пример]
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
class function Method1(Parameter: Pointer): DWORD; static; stdcall;
procedure WMUser(var Msg: TMessage); message WM_USER;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
tid: Cardinal;
begin
Caption := 'Waiting thread...';
CreateThread(nil, 0, @TForm1.Method1, Pointer(Handle), 0, tid);
end;

class function TForm1.Method1(Parameter: Pointer): DWORD;
begin
Sleep(5000);
PostMessage(Integer(Parameter), WM_USER, 0, 0);
Result := 0;
end;

procedure TForm1.WMUser(var Msg: TMessage);
begin
Caption := 'Thread finished';
end;

end.[/more]
Автор: webgirlhb
Дата сообщения: 13.10.2006 14:36
Господа! Не могли бы вы помочь советом мне с решением определенной задачи, не знаю с чего начинать.
Имеется программное обеспечение, которое устанавливается на некоторое количество компьютеров (20-50), территориально распределенное в пределах области. Необходимо, чтобы каждый пользователь работал на месте только со своими данными (из базы на его локальном компьютере), а примерно раз в сутки подключался к интернету и передавал все свои данные на сервер (подключаясь через модем), где все данные от всех пользователей будут собираться в единую базу данных.
Программное обеспечение уже разработано на базе сервера Interbase, проблема теперь в том, как эти данные переносить? Возможно, есть уже готовые решения, или нужно вручную сверять, каких данных не хватает на главном сервере, и переносить каждую запись из базы отдельно?
Если так, то лучше напрямую подключаться к базе и вносить туда изменения, либо пересылать дамп недостающих записей (в виде инструкций SQL - INSERT). Плюс как-то надо учесть не только недостающие записи, но и обновленные, думаю поможет использование полей типа TIMESTAMP.
Важно то, что на сервере не должна быть копия базы каких-либо клиентов, а именно общая для всех клиентов информация, чтобы можно было в любой момент получить доступ как к обобщенным данным, так и к данным в разрезе определенного клиента.
Может, здесь необходимо применять к.-либо трехзвенные технологии???
Помогите, откуда подступать, с чего начинать? Буду рада любым идеям, советам
Автор: RostY
Дата сообщения: 13.10.2006 15:47
сделать во всех таблицах поле "Дата модификации". при INSERT, UPDATE писать в него системную дату (программно, или каким-то тригером, с Интербейсом не работал, поэтому не знаю его возможностей). По концу суток делать селект всех записей с сегодняшней "Датой модификации" и бросать не сервер (например, упаковать zip'ом и по ФТП). Как-то отдельно передавать deleted записи. Если в таблицах есть ключи, то на сервере не очень сложно будет это все реплицировать.
Напрямую подлючаться к базе на сервере, наверно, нежелательно, хотя, смотря какое качество связи.
Автор: OXDBA
Дата сообщения: 13.10.2006 16:01
webgirlhb
Для начала рекомендую ознакомиться с
http://www.osp.ru/text/302/180723/
http://replication.chat.ru/
Стандартные средства
http://www.ibphoenix.com/main.nfs?a=ibphoenix&s=1064848672:146148&page=ibp_replicator#DOWNLOAD
http://www.meta.com.au/index.php?option=com_content&task=view&id=23&Itemid=30
http://www.microtec.fr/copycat/cc/Support.htm
Автор: Arvur
Дата сообщения: 13.10.2006 16:20
webgirlhb
Во-первых, посмотри выше по топику ("Версия для печати"). Тема репликации здесь уже обсуждалась.
В случае IB имеет смысл почитать ibase.ru
В целом смотришь в правильную сторону - действительно, имеет смысл заводить timestamp поля (либо одно, либо два на создание и изменение) и хранить на клиенте дату-время последнего "сеанса связи".

Небольшие комментарии из практического опыта с Firebird:

Цитата:
Как-то отдельно передавать deleted записи.

Лучше заводить флаг-признак удаленности.

Цитата:
Напрямую подлючаться к базе на сервере, наверно, нежелательно

Нормально. Главное, не использовать AutoCommit, а нормально прописать транзакции.

Цитата:
бросать не сервер (например, упаковать zip'ом и по ФТП)

Сэкономить трафик можно, используя прокси. Например ZeBeDee


Цитата:
Может, здесь необходимо применять к.-либо трехзвенные технологии???

Судя по твоему описанию - лесом Это стрельба из пушки по воробьям.

И еще момент - некоторые умники советуют вводить "идентификатор рабочего места". Доп. полем или разделять диапазон ключей. Это сильно усложняет код и если нет насущной необходимости - лучше просто перевести ключи на Int64 (если был Int).
Автор: Sexton
Дата сообщения: 14.10.2006 03:30
webgirlhb, думаю, если при проектировании базы изначально не была предусмотрена репликация, то ее туда уже не пришить. Тем более, если базу проектировал кто-то другой. Лучше проектировать новую базу. Но "безумству храбрых поем мы песню".

Цитата:
И еще момент - некоторые умники советуют вводить "идентификатор рабочего места". Доп. полем или разделять диапазон ключей. Это сильно усложняет код и если нет насущной необходимости - лучше просто перевести ключи на Int64 (если был Int).

Не понял. А чем, собственно, поможет перевод на Int64, если не разделить диапазон ключей (то есть, не выделить для каждого места свой диапазон)? Как гарантировать, чтобы одно и то же значение идентификатора записи не повторилось на разных рабочих местах?
Вводить дополнительное поле или нет, конечно, зависит от логики проектировщика. Но тут надо учитывать, что тогда и поля-ссылки придется делать Int64. В конечном итоге это не лучшим способом скажется на производительности. Впрочем, я не интересовался производительностью использования Int64 на 64-битных процессорах. Может, будет быстрее, чем Int32 (в частности, на Firebird)?
К тому же, я, например, помечаю записи идентификатором пользователя (по которому можно определить ID базы), чтобы можно было определить, кто модифицировал запись. Сливать ID пользователя с ID записи для меня было бы сложно и не логично.
Автор: Arvur
Дата сообщения: 14.10.2006 05:15
Sexton

Цитата:
если при проектировании базы изначально не была предусмотрена репликация, то ее туда уже не пришить
Неправда ваша, батенька Сделать можно все - вопрос в затраченных усилиях. Задача упрощается тем, что тут аплоад в одну сторону и центр один.

Цитата:
А чем, собственно, поможет перевод на Int64
Int64 имеет смысл как альтернатива парному ключу "код_клиента-код_записи". Вероятность выйти за диапазон мала и запросы проще.

Цитата:
Как гарантировать, чтобы одно и то же значение идентификатора записи не повторилось на разных рабочих местах?
Генерировать ключ в центральной базе в момент аплоада. А для локальных (не отправленных) записей использовать свой генератор. Для удобства выборок можно его крутить в минус.

Цитата:
Сливать ID пользователя с ID записи для меня было бы сложно и не логично.
Верю. Какой подход выбирать сильно зависит от специфики задачи. Я исхожу из описанных условий. Решать в итоге webgirlhb, глядя на проект

P.S. Насчет производительности - есть подозрение, что поиск по одному Int64-полю будет быстрее, чем по двум Int32 вне зависимости от логики проца. Но тестов Int64 я не видел.
Автор: Sexton
Дата сообщения: 14.10.2006 08:21
Arvur

Цитата:
Неправда ваша, батенька Сделать можно все - вопрос в затраченных усилиях. Задача упрощается тем, что тут аплоад в одну сторону и центр один.

Ну тогда это задача по реализации "тонких" клиентов. А почему действительно не организовать промежуточное звено стандартными средствами? MIDAS (TClientDataSet) или RemObjects им в руки.

А репликация на неподготовленных для этого базах... Согласен по поводу усилий. Скажем так, усилия на реализацию репликации могут оказаться бОльшими, чем на перепроектирование. Я как-то автоматически думаю при проектировании таблиц, как их будет удобнее релицировать, если понадобится, и по каким правилам. Скажем документы надо реплицировать, но по каким правилам определять, какая версия записи "свежее" - рассматривается индивидуально. А всякие регистры (вычисляемые на основе документов данные) будут пересчитываться автоматически при репликации документов - отдельно их реплицировать не надо.

А чтобы выйти за пределы Int32 на учетной системе (если это не автоматический биллинг и иже с ними), надо постараться. Вряд ли 20-50 пользователям это под силу. Хотя, исключения, конечно, могут быть (или неправильное проектирование, когда при вводе пользователем одной записи в базе плодятся тысячи).

Цитата:
P.S. Насчет производительности - есть подозрение, что поиск по одному Int64-полю будет быстрее, чем по двум Int32 вне зависимости от логики проца. Но тестов Int64 я не видел.

А, ну это понятно. ID записи-то всегда будет Int32, причем уникальность гарантируется только в пределах конкретной базы (при перемещении из одной базы в другу, ID записи в новой базе будет присвоено другое). Второе поле (в моем случае идентификатор пользователя) используется при репликации, ну и в ограничениях прав: чтобы, например, нельзя было редактировать записи, поступившие из другой базы. Правда, для репликации существует еще и третье поле - ID записи в базе-владельце записи (база-владелец определяется по ID пользователя).
Автор: SERGE_BLIZNUK
Дата сообщения: 14.10.2006 09:07
Arvur

Цитата:
Как гарантировать, чтобы одно и то же значение идентификатора записи не повторилось на разных рабочих местах?
Генерировать ключ в центральной базе в момент аплоада. А для локальных (не отправленных) записей использовать свой генератор. Для удобства выборок можно его крутить в минус.

мне кажется, что вы не правы. Тогда в филиалах и центре будут разные базы.

Если делать хорошо и правильно, то нужно обязательно учитывать - принялась ли запись.
Повторять посылку до тех пор, пока не подтвердится.
У нас есть такая самописная система (СУБД Oracle). Схема "звезда". Обнвления идут не только в центральный узел, но и с него (даже так - через него). Все сделанные изменения через триггер пишутся в лог-журнал - по ниму и формуруются репликации.
А вот уникальные ключи ГОРАЗДО лучше (я бы даже сказал ОБЯЗАТЕЛЬНО) разделить по диапазонам - затраты минимальны (в сиквенс добавляется вначале код узла), а выгод - очень много!!!

Хотя, согласен, много зависит от конкретной задачи.

Автор: Arvur
Дата сообщения: 14.10.2006 19:32
SERGE_BLIZNUK

Цитата:
нужно обязательно учитывать - принялась ли запись.

А транзакции на что? Если не обновилась - rollback

Цитата:
Обнвления идут не только в центральный узел

Вооот. Схема совсем другая. Тут, наверное, с уместностью доп. полей я соглашусь

З.Ы. Я, вроде, сразу оговорился что пропагандирую схему для конкретной задачи? Все написанное мной имеет смысл, когда записи от одного клиента видны только ему и центру. Ну и обновления справочников от центра идут всем.
Автор: SERGE_BLIZNUK
Дата сообщения: 14.10.2006 20:26
Arvur

Цитата:
нужно обязательно учитывать - принялась ли запись.

Цитата: А транзакции на что? Если не обновилась - rollback
Автор: Arvur
Дата сообщения: 14.10.2006 20:48
SERGE_BLIZNUK

Цитата:
клиент филиала коннектится напрямую в центральную БД на сервере

Именно так.

Да. Подождем автора, а то скоро на статью настучим
Автор: SERGE_BLIZNUK
Дата сообщения: 14.10.2006 21:25
Arvur

Цитата:

Цитата: Обнвления идут не только в центральный узел
Вооот. Схема совсем другая. Тут, наверное, с уместностью доп. полей я согл
Автор: vserd
Дата сообщения: 16.10.2006 14:12
Arvur

Цитата:
передавать ему метод класса в качестве потоковой функции

Интересная тема... Можешь проиллюстрировать примером кода?

http://forum.ru-board.com/topic.cgi?forum=33&topic=5223&start=17&limit=1
Автор: rs
Дата сообщения: 16.10.2006 15:21
подскажите, пожалуйста,как можно изменить дату последнего обращения файла из дельфи?

есть вот такой код:

procedure TForm1.Button1Click(Sender: TObject);
var
FileHandle: Integer;
dt1,dt2,dt3:PFileTime;
const
FileName = 'C:\1.tst';
begin
getmem(dt1,sizeof(dt1));
getmem(dt2,sizeof(dt1));
getmem(dt3,sizeof(dt1));
FileHandle := FileOpen(FileName, fmOpenWrite or fmShareDenyNone);
if FileHandle > 0 then begin
GetFileTime(FileHandle, dt1, dt2, dt3);
SetFileTime(FileHandle, dt1, dt1, dt1);
end;
FileClose(FileHandle);
freemem(dt1);
freemem(dt2);
freemem(dt3);
end;

по идее все три даты (создания, изменения, открытия) должны стать равными дате создания - однако дата доступа таким образом не изменяется

как решить проблему?
Автор: DroN_S
Дата сообщения: 16.10.2006 16:18

Цитата:
подскажите, пожалуйста,как можно изменить дату последнего обращения файла из дельфи

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

Код:
function SetFileDate(Const FileName : String; Const FileDate : TDateTime): Boolean;
var
FileHandle : THandle;
FileSetDateResult : Integer;
begin
try
try
FileHandle := FileOpen
(FileName,
fmOpenWrite OR fmShareDenyNone);
if FileHandle > 0 Then begin
FileSetDateResult :=
FileSetDate(
FileHandle,
DateTimeToFileDate(FileDate));
result := (FileSetDateResult = 0);
end;
except
Result := False;
end;
finally
FileClose (FileHandle);
end;
end;
Автор: akaGM
Дата сообщения: 16.10.2006 16:32
что означает директива в исходнике?

{%File 'filename.pas'}
Автор: rs
Дата сообщения: 16.10.2006 17:13
DroN_S

Цитата:
тобишь, изменить дату создания файла
нет, из трёх дат (создания, модификации, последнего доступа) нужно на самом деле изменить дату последнего доступа - у меня есть программа, сканирующая файлы - в процессе сканирования фактом своего обращения к сканируемым файлам она изменяет их дату последнего доступа - я же хочу сделать так, как будто моя программа к обрабатываемым (сканируемым) файлам не обращалась вовсе.

это создаёт трудности другой программе (HandyCache) для последующего удаления файлов по дате последнего к ним обращения

в приведенном примере я просто показал, что при попытке установить некоторому файлу все три даты (создания, модификации, последнего доступа) в одно и то же значение (для простоты и наглядности) - с датами создания, модификации это проходит, а дата последнего обращения не изменяется из моего программмного кода - она ставится системой как дата-время собственно открытия файла в моей программе примере
Автор: DroN_S
Дата сообщения: 16.10.2006 17:18
rs
в общем, скажи одно, что тебе нуждно изменить:
дату создания?
дату изменения?
дату открытия?
ФАЙЛА!!!!
Автор: rs
Дата сообщения: 16.10.2006 17:30
DroN_S
дату открытия (LastAccess)


Добавлено:
DroN_S
я просто сразу показал в примере, что методом SetFileTime именно ЭТА дата почему-то и не меняется
Автор: DroN_S
Дата сообщения: 16.10.2006 17:47
rs
а через FileSetDate не пробывал
Автор: rs
Дата сообщения: 16.10.2006 17:52
DroN_S
хех
а ларчик просто открывался - нужно просто убрать
FileClose(FileHandle);


хотя во всех найденных примерах в сети стоит именно закрытие(!) файла - но именно нормальное закрытие и сбрасывает дату последнего доступа к файлу, установленную в моей программе

однако возникает вопрос - ресурс FileHandle надо же всё-таки освободить? ведь при сканировании десятков тысяч файлов будет вызван десятки тысяч раз метод
FileHandle := FileOpen
и ни разу закрытие хэндлов

количество занятой (неосвобождённой памяти), наверное будет расти с каждым открытием новго файла при их массовомй обработке?

как правильно освободить память после FileOpen без закрытия файла FileClose

Добавлено:
DroN_S
Цитата:
а через FileSetDate не пробывал
меняется только дата создания
Автор: OOD
Дата сообщения: 16.10.2006 18:00
не подскажете исходник просого джойнера на делфи?
такой чтобы 2 Exe Разбивал на какой нибуть стринг , а потом по очереди собирал их и запускал...
Автор: DroN_S
Дата сообщения: 16.10.2006 18:23
OOD
тобишь тебе надо разбить файл на яасти, а потом его склеить воедино обратно?
rs
круто
Автор: rs
Дата сообщения: 16.10.2006 18:26
DroN_S
а как с этим быть:

Цитата:
количество занятой (неосвобождённой памяти), наверное будет расти с каждым открытием новго файла при их массовомй обработке?

как правильно освободить память после FileOpen без закрытия файла FileClose


я ж не могу бросать незакрытыми десятки тысяч хэндлов...

Добавлено:
какой-нибудь FreeHandle вместо FileClose - освободить хэндл без закрытия файла... нет такого?
Автор: DroN_S
Дата сообщения: 16.10.2006 18:32

Цитата:
я ж не могу бросать незакрытыми десятки тысяч хэндлов...

так ты можешь закрывать только хэндл окна
CloseHandle(FileHandle)

Страницы: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667

Предыдущая тема: Событие STFilter(DBGridEh) ???


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.