2009-12-02 4 views

답변

4

또한 스레드에서 프로 시저를 실행할 수도 있습니다. OnTerminate 이벤트를 사용하여 결과를 가져옵니다. 그렇습니다. 요즘 .NET과 C#에서는 비동기 적으로 메소드를 실행하는 쉽고 편리한 방법으로 버릇이 없지만 델파이에서 작동하는 방식입니다.

+0

저는 C# jeje에서 델파이로 변환하려고 시도하고 있습니다. (.NET을 사용하고 싶지 않기 때문에) 당신이 말하는 것을 보았습니다. 감사. – Sebastian

+0

나는 마침내 간단한 BeginThread로 작업하게 만들었고, 나는 프로 시저의 결과에 대해서는별로 신경 쓰지 않았다. 당신의 메시지를 보내 주셔서 감사합니다. – Sebastian

16

VCL에 즉시 사용 가능한 것이 있는지 묻는 경우 대답은 no입니다. 그러나 Andreas Hausladen의 라이브러리 인 AsyncCalls 라이브러리에 연결된 작은 단위의 형식으로 아주 비슷한 것을 얻을 수 있습니다. 그것은 구성 요소가 아니므로 자격이 있다고 생각합니다. 그것은 또한 버전 5부터 델파이를 지원합니다. 대단히 좋습니다.

편집 : 당신이 그것을 실행하지 않았기 때문에 내가 예를 추가 할 것입니다

. 호출 코드에서 블로킹을 당하면 함수가 반환 한 IAsyncCall 인터페이스 포인터에 대한 참조가 유지되지 않는 것이 문제입니다. 따라서 임시 참조가 범위를 벗어나면 인터페이스를 구현하는 객체가 즉시 삭제됩니다. 소멸자는 VCL 스레드의 컨텍스트에서 호출되며 WaitForSingleObject() 또는 이와 유사한 함수를 호출하여 작업자 스레드가 완료 될 때까지 대기합니다. 그 결과 VCL 스레드가 차단됩니다. 당신이 인터페이스 포인터에 대한 참조를 유지하는 경우

당신은 올바른 동작을 얻을 것이다 : 비활성화하고 Interval 매우 짧은을 할 수있는 타이머를 설정

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    Timer1: TTimer; 
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
    procedure Button1Click(Sender: TObject); 
    procedure Timer1Timer(Sender: TObject); 
    private 
    fAsyncCall: IAsyncCall; 
    procedure WaitForIt(ADelay: integer); 
    end; 

를, 50 밀리 말한다. 버튼을 클릭하면 비동기 작업이 시작됩니다.

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    Button1.Enabled := FALSE; 
    fAsyncCall := AsyncCall(WaitForIt, 1000); 
end; 

procedure TForm1.WaitForIt(ADelay: integer); 
begin 
    Sleep(ADelay); 

    EnterMainThread; 
    try 
    Randomize; 
    Color := RGB(Random(256), Random(256), Random(256)); 
    Timer1.Enabled := TRUE; 
    finally 
    LeaveMainThread; 
    end; 
end; 

다른 작업은 시작할 수 없습니다. 이 EnterMainThread()LeaveMainThread()을 사용하여, 피 호출 방법 문의 양식에 액세스하는 것도 가능하다 방법

procedure TForm1.Timer1Timer(Sender: TObject); 
begin 
    Timer1.Enabled := FALSE; 
    Assert((fAsyncCall <> nil) and fAsyncCall.Finished); 
    fAsyncCall := nil; 
    Button1.Enabled := TRUE; 
end; 

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
begin 
    CanClose := (fAsyncCall = nil) or fAsyncCall.Finished; 
end; 

참고 종료 후 그 형태를 통보하고 인터페이스 참조 재설정 타이머를 가능하게한다.

위의 코드가 절대 최소치는 아니며, 일부 아이디어 만 제공합니다.

+0

어제 라이브러리를 보았지만 코드를 최소한으로 유지하고 싶었습니다. 결국 어쨌든 사용하게 될 것입니다. 단순한 .pas 단위예요? – Sebastian

+0

네, 단지 2와 3 사이의 kLOC입니다. 그래서 그것은 이미 매우 적습니다. 나는 이것이 이길 수 있다고 생각하지 않는다. 인터페이스는 매우 간단합니다. 모든 털이 많은 것들은'implementation' 부분에 있습니다 ;-) 호출이 끝날 때까지'IAsyncCall' 참조를 유지하십시오. 그렇지 않으면 마지막 참조 횟수 감소가 차단됩니다. – mghie

+0

이것이 최고의 솔루션이 될 것 같습니다. 대단히 감사합니다. – Sebastian

관련 문제