5

データベースに接続している間、アプリケーションをフリーズさせずに、スプラッシュ画面を表示しようとしています。通常の接続 (ADO 経由の MSSQL への接続) には約 300 ミリ秒かかりますが、これにより Windows でメイン スレッドが「応答していません」と表示されることはありません。

ただし、(a) ネットワーク エラーまたは (b) 構成ミス (SQL サーバーのホスト名/インスタンスが無効) の場合は、タイムアウトに 60 秒かかります。これにより、アプリケーションが応答しなくなるだけでなく、フリーズするときにエラーやメッセージを表示することがほとんど不可能になります。接続を開始する前にメッセージをポップアップ表示することはできましたが、メイン スレッドが 60 秒間ブロックされた場合、実際には解決策がありません。

解決策は、接続をバッ​​クグラウンド スレッドに移動することです。これにより、次のコードが生成されます。

  1. バックグラウンド接続を確立する TThread クラスと、シグナルをメイン スレッドに送り返すために使用される TEvent などの SyncObj です。

  2. 次のコードを使用したメイン スレッドのループ:

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

これは正しい方法ですか?私の躊躇には、上記のソリューションの次の要素が含まれます。

A. Application.ProcessMessages を呼び出しますが、これは極端なコードの臭いだと思います (これは、この規則の許容される例外である可能性があります)。

B. アプリケーションの起動にスレッドを導入していますが、バグが発生するのではないかと心配しています。

競合状態がなく、ADO へのバックグラウンド接続を行うことができ、安全なアプローチであることがわかっている参照実装を誰かが持っている場合、それは本当に役に立ちます。それ以外の場合は、一般的なヒントまたは部分的な例が適切です。

4

2 に答える 2

4

すべてのスレッドが独自の ADO 接続を使用する必要があるという既知の制限があるため (つまり、他のスレッドで作成された接続オブジェクトを使用することはできません)、私が考えることができる唯一のオプションは、データベースに接続するスレッドを作成することです。接続が確立されるかタイムアウトに達すると、イベントについてメインスレッドに通知し、接続を閉じる/破棄します。その間、メイン スレッドは、そのスレッドからのメッセージを待って、スプラッシュまたは進行状況を表示できます。したがって、間違ったパスワードまたは到達不能なホストのケースを排除します。2 番目のスレッドが接続できれば、メイン スレッドもすぐに接続できるという合理的な仮定があります。

于 2012-05-22T08:44:12.343 に答える
1

スレッド間通信にはいくつかの方法があります。私は通常、ウィンドウのメッセージを使用します。まず、カスタム メッセージとメッセージ ハンドラーをフォームで定義します。次に、カスタム スレッドからメイン スレッドに通知する必要がある場合は、PostMessage 関数を使用して通知を送信します。

ここに小さなチュートリアルがあります。

OmniThreadLibraryなど、スレッド化にライブラリを使用することもできます。

于 2012-05-21T06:25:49.587 に答える