2012-05-21 35 views
5

Tôi đang cố hiển thị màn hình giật gân và không đóng băng ứng dụng, trong khi nó kết nối với cơ sở dữ liệu. Các kết nối thông thường (tới MSSQL qua ADO) mất khoảng 300 msec và điều này không làm cho luồng chính hiển thị "không phản hồi" trên các cửa sổ.Hiển thị màn hình giật gân trong khi kết nối cơ sở dữ liệu (có thể mất nhiều thời gian) chạy

Tuy nhiên, trong trường hợp (a) lỗi mạng hoặc (b) lỗi cấu hình (tên máy chủ/máy chủ SQL không hợp lệ), mất 60 giây để hết thời gian chờ. Điều này không chỉ làm cho ứng dụng không đáp ứng, nhưng hầu như không thể hiển thị bất kỳ lỗi hoặc thông báo nào khi nó đóng băng. Tôi có thể bật lên một tin nhắn trước khi tôi bắt đầu kết nối nhưng thực sự không có giải pháp nào khi chuỗi chính bị chặn trong 60 giây.

Giải pháp dường như là di chuyển kết nối đến một chuỗi nền. Điều này dẫn đến đoạn mã sau:

  1. một TThread-class mà làm cho các kết nối nền và một số SyncObj như một TEvent sử dụng để gửi một tín hiệu trở lại chủ đề chính.

  2. Một vòng lặp trong các chủ đề chính với mã này:

    BackgroundThread.StartConnecting; 
    while not BackgroundThread.IsEventSignalled do begin 
        Application.ProcessMessages; // keep message pump alive. 
    end; 
    // continue startup (reports error if db connection failed) 
    

Đây có phải là cách đúng đắn để đi đâu? do dự của tôi liên quan đến các yếu tố sau của giải pháp trên:.

A. Tôi sẽ gọi Application.ProcessMessages, mà tôi xem xét một mùi code cực đoan (Điều này có thể là một ngoại lệ cho phép đối với quy tắc này)

B. Tôi đang giới thiệu các chủ đề trong quá trình khởi động ứng dụng và tôi lo lắng về việc giới thiệu các lỗi.

Nếu có ai thực hiện tham chiếu được biết là không có điều kiện chủng tộc, có thể thực hiện kết nối nền với ADO và được biết đến là phương pháp an toàn, điều đó thực sự hữu ích. Nếu không thì các mẹo chung hoặc ví dụ một phần là tốt.

+5

Cho rằng kết nối bình thường chỉ mất 300ms, tại sao không thay đổi thời gian chờ (ví dụ: 1000ms)? – awmross

+4

Cách hiển thị màn hình giật gân từ chủ đề nền: http: // stackoverflow.com/questions/388506/display-splash-screen-in-delphi-when-main-thread-is-busy – Harriv

+1

Vấn đề này là một trong những trường hợp sử dụng chính để hiển thị giao diện người dùng từ một chủ đề khác với chủ đề GUI chính –

Trả lời

4

Do giới hạn được biết rằng mỗi luồng phải sử dụng kết nối ADO riêng của nó (nghĩa là bạn không thể sử dụng đối tượng kết nối được tạo trong chủ đề khác), tùy chọn duy nhất tôi có thể tạo ra một chuỗi sẽ tạo kết nối tới cơ sở dữ liệu và sau khi kết nối được thiết lập hoặc hết thời gian chờ, hãy báo hiệu chuỗi chính về sự kiện và đóng/hủy kết nối. Các chủ đề chính có thể trong khi chờ đợi hiển thị giật gân hoặc tiến bộ, chờ đợi một tin nhắn từ chủ đề đó. Vì vậy, bạn loại bỏ trường hợp với mật khẩu sai hoặc máy chủ không thể truy cập. Có một giả thiết hợp lý, rằng, nếu luồng thứ hai có thể kết nối, thì luồng chính sẽ có thể kết nối ngay sau đó.

+0

+1, đồng ý, nhưng bạn sẽ cần phải di chuyển tất cả các hành động cơ sở dữ liệu vào chuỗi đó, bởi vì bạn không thể chuyển đối tượng kết nối tới luồng chính từ công nhân của bạn. Và cần phải có chúng trong một chủ đề chính, ví dụ: trong trường hợp bạn đang sử dụng các thành phần nhận biết dữ liệu. – TLama

+1

Anh ấy nói rằng bạn chỉ mở và sau đó chỉ cần đóng kết nối đó. Vì vậy, bạn chỉ xử lý một kết nối ban đầu như một tính năng "kiểm tra lỗi" của ứng dụng của bạn. Bạn vẫn phải làm lại logic kết nối trong luồng chính. –

+0

@Warren, nếu bạn chỉ định xác minh xem có thể kết nối và sau đó kết nối lại với cùng một cài đặt kết nối trong chuỗi chính thì bạn có thể sử dụng mã từ câu trả lời đã xóa (hiện thực sự đã xóa) của tôi không. – TLama

1

Có một số phương pháp liên lạc giữa các luồng. Tôi thường sử dụng tin nhắn của Window. Trước tiên, tôi xác định thông điệp theo yêu cầu và trình xử lý tin nhắn trong một biểu mẫu. Sau đó, khi tôi cần phải thông báo chính chủ đề từ chủ đề tùy chỉnh, tôi sử dụng chức năng PostMessage để gửi thông báo.

Hướng dẫn nhỏ here.

Bạn cũng có thể sử dụng thư viện để tạo luồng, ví dụ: OmniThreadLibrary.

+0

Tôi biết. BUT Tôi đang tự hỏi cụ thể về việc chặn khởi động ứng dụng của tôi - làm thế nào để làm điều đó - vòng lặp tin nhắn-máy bơm của riêng tôi (gọi các thông điệp application.process) hoặc cái gì khác? –

+0

Tôi đã kết thúc hiển thị màn hình giật gân trong chuỗi .. Xem liên kết trong nhận xét của tôi cho câu hỏi. – Harriv