2010-09-27 30 views
6

Tôi chưa bao giờ làm việc với các chủ đề trước đây, và bây giờ tôi đang cố tạo một chuỗi với một truy vấn để kiểm tra trạng thái cơ sở dữ liệu. Truy vấn như sau:cách viết và thực hiện một chủ đề

select (*) as DBCount from v$datafile where status in 'OFFLINE';.

Truy vấn này trả về tổng số tất cả cơ sở dữ liệu ngoại tuyến. Bây giờ tôi muốn tạo một thread trong Delphi sẽ thực hiện truy vấn này trong nền của ứng dụng của tôi khi tôi chạy nó và hiển thị các kết quả trên nhãn.

+0

Tôi đã xóa thẻ pthread vì không thực sự tương thích với thẻ delphi. – mghie

Trả lời

0

Ở Delphi có TThread lớp học. Bạn có thể tạo chủ đề như vậy bằng cách sử dụng thuật sĩ đơn giản từ Delphi IDE (trong Turbo Delphi: File-> New-> Delphi Projects-> Delphi Files-> Thread Obcjet). Trong hàm tạo của nó tạo kết nối tới cơ sở dữ liệu và trong phương thức Execute bạn có thể tạo vòng lặp cơ sở dữ liệu truy vấn đó, cập nhật một số biến toàn cầu (NOT được khai báo là threadvar) và ngủ một thời gian.

+2

Đưa kết quả vào một 'threadvar' sẽ làm cho nó không thể cho bất kỳ chủ đề khác để có được kết quả. Làm thế nào mà sẽ hữu ích? – mghie

+1

upps, xin lỗi, lỗi của tôi, tất nhiên điều này sẽ là biến bình thường. –

+0

Chỉ cần tự hỏi tại sao câu trả lời này được downvoted (ngay cả mặc dù threadvar) vì tôi nghĩ rằng đó là hữu ích và cung cấp cho OP một nơi để bắt đầu và để bắt đầu đọc về. Nó sẽ là tuyệt vời nếu SO chỉ cho phép downvote động cơ ... – Remko

7

Đa luồng là khó. Bạn có thể tốt hơn bằng cách sử dụng một khuôn khổ luồng đơn giản như AsyncCalls.

Tiếp theo chủ đề StackOverlow có thể cung cấp cho bạn thêm thông tin về làm thế nào để giải quyết vấn đề của bạn:

Delphi - Threading frameworks

How Do I Choose Between the Various Ways to do Threading in Delphi?

Delphi thread that waits for data, processes it, then resumes waiting

+0

Một khung Threading đẹp khác là OmniThreadLibrary của gabr: P http://otl.17slon.com/ – Remko

+0

@Remko: Nó được bao gồm trong các chủ đề mà tôi đã đề cập đến. – gabr

0

Ở đây bạn có thể tìm thấy một cuộc thảo luận về việc sử dụng chủ đề trên DataBase.

Simple Thread Sample Delphi

Có một số mã có thể có ích cho bạn.

Trân trọng.

1

Đ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.

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