2010-03-29 4 views
5

Câu hỏi của người mới: Tôi có đơn đăng ký biểu mẫu. Nó có một chuỗi riêng biệt mà làm cho một cuộc gọi dịch vụ web, và sau đó gửi kết quả của cuộc gọi đến biểu mẫu chính.Tôi có nên giải phóng một đối tượng Delphi được tự động khởi tạo từ một cuộc gọi dịch vụ web không?

Trong chủ đề của tôi, sau X giây đã trôi qua (sử dụng một TTimer), tôi gọi:

procedure TPollingThread.OnTimer(Sender: TObject); 
var 
SystemProbeValues : TCWProbeValues; 
begin 
SystemProbeValues := Remote.Run.GetSystemProbeValues; 
PostMessage(ParentHandle, WM_APIEVENT ,Integer(apiMultiCellStatus), Integer(SystemProbeValues)); 
end; 

Các Remote.Run.GetSystemProbeValues ​​chức năng đã nguyên mẫu sau:

function GetSystemProbeValues : TCWProbeValues; stdcall; 

Và TCWProbeValues là một mảng động của các đối tượng TCWProbeValue (tất cả đều xuất phát từ TRemotable).

Ở dạng chính của tôi, tôi nhận được thông báo tốt và đúc các lParam trở lại TCWProbeValues:

procedure TFrmCWMain.OnAPIEvent(var msg: TMessage); 
begin 
ProbeValues := TCWProbeValues(msg.LParam); 
end; 

Câu hỏi của tôi là, cho rằng mảng động và các đối tượng của nó được tạo ra bởi hệ thống Delphi HTTORIO, ai chịu trách nhiệm giải phóng chúng? Delphi có nghĩ rằng bộ nhớ có thể sử dụng lại sau khi chức năng OnTimer của tôi quay trở lại không? (Và trong trường hợp nào, may mắn thuần khiết của nó là trình xử lý tin nhắn biểu mẫu chính của tôi thực sự có thể đọc bộ nhớ được tham chiếu bởi LParam của thông báo?) Hay đúng hơn, đó là trách nhiệm của tôi để giải phóng đối tượng được tự động khởi tạo bởi yêu cầu HTTPRIO?

Rất cám ơn, hãy hét lên nếu điều trên cần thêm chi tiết/mã và tôi sẽ thêm vào đó!

Chúc mừng, Duncan

Trả lời

4

TRemotable cung cấp quản lý đời qua tài sản DataContext của nó, vì vậy thời gian chạy SOAP sẽ giải phóng các đối tượng chính nó. Miễn là đối tượng dữ liệu bối cảnh tồn tại, mọi thứ được phân bổ cũng sẽ tồn tại. Nếu bạn muốn yêu cầu quyền sở hữu và trách nhiệm đối với một đối tượng, chỉ cần xóa thuộc tính DataContext của nó. (Đó có thể là những gì bạn sẽ muốn làm trong trường hợp này vì thông báo sự kiện API của bạn có thể được xử lý sau khi sự kiện SOAP đã chấm dứt.)


Một vấn đề trong mã của bạn là bạn đang chuyển động mảng qua tin nhắn đã đăng. Khi thủ tục OnTimer của bạn trả về người gọi, mảng động được tham chiếu bởi SystemProbeValues sẽ có số lượng tham chiếu bị giảm. Nếu chủ đề khác chưa xử lý thông báo (và có thể là chưa), thì mảng động có thể đã bị phá hủy vào thời điểm nó thực hiện để xử lý thông báo đó.

Cách dễ dàng xung quanh đó là xóa tham chiếu trong trình xử lý sự kiện của bộ hẹn giờ mà không làm giảm số tham chiếu và sau đó thực hiện ngược lại trong trình xử lý tin nhắn. Sau khi bạn gửi tin nhắn, xóa các biến:

LParam(SystemProbeValues) := 0; 

Trong xử lý thông điệp của bạn, hãy bỏ giá trị cũ của ProbeValues biến toàn cầu và gán giá trị mới như thế này:

ProbeValues := nil; 
LParam(ProbeValues) := Msg.LParam; 

Một vấn đề ẩn trong mã của bạn có thể là việc sử dụng TTimer trong một chuỗi không phải VCL. Lớp đó tạo ra một cửa sổ xử lý để chia sẻ giữa tất cả các cá thể của lớp.Trừ khi bộ đếm thời gian của bạn là chủ đề duy nhất trong chương trình sử dụng TTimer, có thể bạn sẽ gặp sự cố, với chức năng chạy sai chuỗi hoặc chức năng không chạy chút nào. Thay vì TTimer, bạn có thể sử dụng SetTimer để tạo hẹn giờ OS theo cách thủ công hoặc bạn có thể tạo waitable timer, có thể phù hợp hơn để sử dụng trong chuỗi không cần đáp ứng với hành động của người dùng.