Điều này khá dễ thực hiện khi sử dụng AsyncCalls. Giả sử mã không có chuỗi của bạn trông như thế này (bỏ qua tất cả các lỗi xử lý):
Query := 'select (*) as DBCount from...';
ExecuteSQL(SqlConnection,Query);
SqlResult := GetSqlResult(SqlConnection);
SqlRow := GetSqlRow(SqlResult);
MyLabel.Text := SqlRow[0];
...Go on to do other things...
Trường hợp dòng thứ hai đang chặn (chờ máy chủ trả lời). mã mới của bạn sẽ trông như thế này:
uses AsyncCalls; //added to your existing uses statement
...
procedure DoesSomething();
var Thread: TAsyncCall; //your interface to AsyncCalls
procedure AsyncSqlCall(); //this is a LOCAL procedure
Query := 'select (*) as DBCount from...';
ExecuteSQL(SqlConnection,Query);
SqlResult := GetSqlResult(SqlConnection);
SqlRow := GetSqlRow(SqlResult);
EnterMainThread;
try
Assert(GetCurrentThreadId = MainThreadId);
MyLabel.Text := SqlRow[0];
finally
LeaveMainThread;
end;
begin //this begins proc DoSomething()
...
Thread := LocalAsyncCall(@AsyncSqlCall);
...Go on to do other things...
end;
Tất cả chúng tôi đã làm là đưa các cuộc gọi SQL chặn trong một proc địa phương và nói AsyncCalls để thực hiện nó trong chủ đề khác, trong khi các chủ đề chính tiếp tục thực hiện. Phần khó khăn duy nhất là sử dụng VCL, vốn không an toàn. Vì vậy, tôi đã có dòng đó chạy một cách an toàn trong chủ đề chính.
Nếu lúc nào đó bạn cần phải chắc chắn thread async đã hoàn tất, bạn sẽ thực hiện dòng này để ngăn chặn các chủ đề chính cho đến AsyncSqlCall chấm dứt:
Thread.sync;
Điều thật sự tốt đẹp ở đây là rằng AsyncCalls xử lý tất cả các công cụ về việc tạo một hồ bơi thread, tạo chủ đề, vv Mặc dù không được hiển thị trong ví dụ này, bạn có thể chuyển các biến cho luồng của bạn và trả về một giá trị. Bạn không cần phải sử dụng một proc địa phương, nhưng làm như vậy cung cấp cho nó truy cập vào tất cả các vars địa phương. Bạn có thể làm cho tất cả điều này toàn cầu, và sau đó khởi động các chủ đề Async trong một thói quen, và thử nghiệm cho hoàn thành của nó trong khác.
Hạn chế:
chủ đề async của bạn không phải chạm vào (đọc hoặc viết) bất cứ điều gì nhưng các biến riêng của mình, và chủ đề chính của bạn không phải chạm vào chúng trong khi thread async đang chạy. BẠN phải mã nó theo cách đó. Không có gì ngăn cản bạn tạo ra sự hỗn loạn. Trong ví dụ trên, chủ đề chính của bạn không được chạm vào Query, SqlConnection, SqlResult và SqlRow. Nếu bất kỳ phần nào trong mã của bạn đã sử dụng một trong các vars đó trước cuộc gọi Thread.sync, mã của bạn sẽ hoạt động - nhưng hãy ném ngoại lệ vào những nơi lạ mà bạn không bao giờ mong đợi. Vì vậy, hãy giữ nó đơn giản.
Chuỗi không đồng bộ của bạn không được sử dụng VCL. Mẫu trên cho thấy một trong nhiều cách để vượt qua giới hạn này một cách an toàn.
Cuối cùng:
AsyncCalls không phải là một khung Multi-Threading đầy đủ. Nó chỉ là một cách gọi procs & chức năng không đồng bộ (tức là không chờ đợi). Đừng cố gắng đẩy nó quá xa - theo ý tôi, đừng cố làm cho nó trở thành nền tảng của một chương trình đa nhiệm hoàn toàn.
Tôi đã xóa thẻ pthread vì không thực sự tương thích với thẻ delphi. – mghie