2017-10-31 14 views
16

Tôi vui lòng yêu cầu bạn tư vấn về vấn đề sau tôi gặp phải ở Delphi với khối try/except.Làm cách nào để bắt ngoại lệ trong sự kiện TDataModule.OnCreate?

Tôi có một ứng dụng đơn giản - một trong những MainForm có tên fr_MAIN và một TDataModule có tên DM. DM không phải là tính năng tự động tạo ra, nhưng nó được tạo ra tại thời gian chạy trong fr_MAIN 's Button2.OnClick sự kiện:

procedure Tfr_MAIN.Button2Click(Sender: TObject); 
begin 
    try 
    DM := TDM.Create(nil); 
    Showmessage('DM started!'); 
    except 
    on E:Exception do 
    begin 
     Showmessage('DM not started!'); 
    end; 
    end; 

DM có một số mã trong sự kiện OnCreate của nó:

procedure TDM.DataModuleCreate(Sender: TObject); 
begin 
    raise Exception.Create('this is error!'); 
    // DM code here ... 
end; 

Vấn đề là khi Tôi nhấp vào Button2, tôi nhận được thông báo ngoại lệ 'this is error!', phần còn lại của DM code here không chạy - điều đó là chính xác! Nhưng sau đó tôi cũng nhận được thông báo 'DM started!' thay vì thông báo 'DM not started!'.

Ngoại lệ được tăng lên bởi DM ngắt hành động nhưng không bị bắt trong khối except của biểu mẫu!

Tại sao điều này?

+0

Theo mặc định, 'TApplication' cho' TDataModule' nuốt một ngoại lệ được nêu ra bởi sự kiện 'TDataModule.OnCreate' (xem câu trả lời của Tom để biết chi tiết cụ thể). Để làm những gì bạn đang yêu cầu, bạn nên ghi đè lên hàm khởi tạo ảo 'TDataModule.Create()' để tăng ngoại lệ, thay vì sử dụng sự kiện 'TDataModule.OnCreate'. –

Trả lời

20

TDataModule có xử lý đặc biệt các ngoại lệ được nêu trong sự kiện OnCreate của nó.

Trường hợp ngoại lệ được xử lý ở đây:

procedure TDataModule.DoCreate; 
begin 
    if Assigned(FOnCreate) then 
    try 
    FOnCreate(Self); 
    except 
    if not HandleCreateException then // <-- here 
     raise; 
    end; 
end; 

function TDataModule.HandleCreateException: Boolean; 
begin 
    if Assigned(ApplicationHandleException) then 
    begin 
    ApplicationHandleException(Self); // <-- here 
    Result := True; 
    end 
    else 
    Result := False; 
end; 

Theo mặc định, TApplication gán TApplication.HandleException()-ApplicationHandleException:

constructor TApplication.Create(AOwner: TComponent); 
var 
    ... 
begin 
    inherited Create(AOwner); 
    ... 
    if not Assigned(System.Classes.ApplicationHandleException) then 
    System.Classes.ApplicationHandleException := HandleException; // <-- here 
    if not Assigned(System.Classes.ApplicationShowException) then 
    System.Classes.ApplicationShowException := ShowException; 
    ... 
end; 

Vì vậy, TDataModule.DoCreate() đang thu hút sự ngoại lệ và đi qua nó để TApplication.HandleException(), mà sau đó sẽ hiển thị một hộp thoại bật lên theo mặc định. Và kể từ TDataModule.HandleCreateException() sau đó trả về True, ngoại lệ bị bắt không được nâng lên. Ngoại lệ hiện được xem là đã xử lý, cho phép chương trình tiếp tục bình thường với cuộc gọi Showmessage('DM started!'); của nó.

Để tránh hộp thoại bật lên khi ngoại lệ xảy ra, bạn có thể gán một handler TApplication.OnException sự kiện:

Vcl.Forms.TApplication.OnException

Sử dụng OnException để thay đổi hành vi mặc định xảy ra khi một ngoại lệ không được xử lý bởi mã ứng dụng. Sự kiện OnException xử lý được gọi tự động trong phương thức HandleException.

Nhưng ngoại lệ vẫn sẽ bị bắt và loại bỏ bởi TDataModule.DoCreate(). Nếu bạn muốn tránh điều đó, do đó, ngoại lệ lan truyền lên ngăn xếp cuộc gọi, không nêu ngoại lệ từ sự kiện TDataModule.OnCreate. Ghi đè lên hàm tạo ảo TDataModule.Create() và tăng ngoại lệ từ đó lên thay thế.

: Điều tương tự cũng xảy ra trong TCustomForm.

+1

Cảm ơn @Remy cho các chỉnh sửa của bạn. Xuất sắc. –

+0

Cảm ơn bạn rất nhiều ông Lebeau và ông Brunberg! Tôi đã học được điều gì đó rất quan trọng lần này về việc mọi thứ diễn ra như thế nào trên một sự kiện Tạo TDataModule. Để chiếu sáng nhiều hơn về điều này, trong một tương lai gần DM sẽ được tạo ra (và được phát hành) từ một TService - điều này làm tôi phức tạp hơn. Tôi đã có ý tưởng mà bạn trình bày, nhưng với kỹ năng của tôi trên Delphi ngay bây giờ tôi không ở trong đó - ít nhất là cho đến khi tôi thiết lập TService - cho đến thời điểm này tôi sẽ nhận được bằng thực tế không ngoại trừ Raise Exception.create bên trong DM.Create từ một đơn vị khác cảm ơn bạn rất nhiều Trân trọng – altink

Các vấn đề liên quan