당신의 OTL 작업이 기준과 일치하는 회사의 정렬 된 목록로드 할 필요가있는 경우 :
// create and open query to fetch list of companies
while not qryCompanies.Eof do begin
C := TCompany.Create;
try
C.LoadFromDataset(qryCompanies);
Companies.Add(C);
except
C.Free;
raise;
end;
qryCompanies.Next;
end;
C
이 회사의 비즈니스 오브젝트입니다. 객체 (TCompany
) 또는 객체가 구현 한 인터페이스 (ICompany
)가 될 수 있습니다. Companies
은 TList<TCompany>
또는 TList<ICompany>
입니다. 작업의 끝에서 당신은 VCL 스레드에 기업의 목록을 보내 :
Task.Comm.Send(TOmniMessage.Create(MSGID_LIST_OF_COMPANIES, Companies));
를 양식에 당신이 당신의 작업을 모니터링하는 otlEventMonitor
인스턴스의 OnTaskMessage
이벤트를 처리 기업의 목록을 표시 할 위치 :
procedure TListBaseFrame.otlEventMonitorTaskMessage(
const task: IOmniTaskControl);
var
MsgID: word;
MsgValue: TOmniValue;
begin
task.Comm.Receive(MsgID, MsgValue);
Assert(MsgValue.IsInterface);
if fLoaderTask = task then begin
SetLoadedData(MsgID, MsgValue.AsInterface); // or MsgValue.AsObject);
fLoaderTask := nil;
end;
end;
기업 목록이 이전 목록을 대체하며 그리드에 표시 될 수 있습니다.
마찬가지로 회사 개체/인터페이스 하나를 반환하고 표시하고 편집 할 수 있습니다. 생각의 가치가
두 가지 : 인터페이스
지금까지 선호하는 경우 객체, 멀티 스레드 프로그램을 작성은을 재고 할 수있는 이유가 될 수 있습니다. 백그라운드 스레드에서 객체를 만든 다음 VCL 스레드에 전달하고 백그라운드 스레드에서 객체를 잊어 버리면 객체가 제대로 작동 할 수 있습니다. 그러나 응용 프로그램에서 개체를 캐싱하고 아직로드되지 않았거나 변경된 데이터베이스의 레코드 만로드하면 성능이 훨씬 향상 될 수 있음을 알았습니다.모든 테이블에는 변경 색인 (64 비트 정수, 시간 스탬프가 잘 작동 할 수 있음)이 첨부되어 있으며 모든 업데이트와 함께 변경됩니다. 대신
select * from foo where (...) order by (...)
를 실행의 난 단지 이제까지
select id, change_index from foo where (...) order by (...)
다음 캐시에 체크 실행 여부를 동일한 ID 그래서 캐시를 반환하는 경우 이미 존재 (기본 키) 및 변경 인덱스 오브젝트 새 비즈니스 오브젝트를 작성하지 않고 모든 컬럼을로드하는 경우에만.
개체를 캐시하면 다중 스레드에서 개체를 참조하게되고 소유권 문제가 너무 복잡해 지므로 참조 카운트를 기반으로하는 평생 관리가 정상적으로 유지되는 유일한 방법입니다. 객체 대신 인터페이스를 사용하면이 점에서 많은 도움이됩니다.
여러 스레드가 동시에 액세스 할 수있는 경우, 각 Business Object에 동기화 오브젝트를 추가해야합니다. 물론 가능하지만 추가적인 복잡성과 잠재적 교착 상태가 발생할 수 있습니다. 비즈니스 오브젝트를 변경 불가능한 것으로 구현하면 잠금이 필요하지 않습니다. 나는 그 접근 방식을 점점 더 많이 사용하고 있으며 익숙해지기까지는 많은 일을 단순화 할 수 있습니다.
완벽한! 그게 정확히 제가 누락 된 것입니다 ... 결과를 다른 스레드로 가져 오는 방법. 대단히 감사합니다! – Holgerwa
+1 훌륭한 답변! – jpfollenius
평소와 같이 훌륭한 답변입니다! – gabr