すべてのGUIコードはメインスレッドから実行する必要があり、そのルールに従っているように見えます。
Sleep
を呼び出すと、呼び出しスレッドはタイムアウトが経過するまでコードを実行しません。メインスレッドからSleep
を呼び出すと、タイムアウトが経過するまでメッセージキューはポンピングされません。したがって、アプリ全体がフリーズしているように見えます。
Sleep
を1つのフォームから呼び出すと、別のフォームに影響するのはなぜですか?すべてのGUIコンポーネントがメインスレッドの単一メッセージキューから提供されるためです。キューをポンピングすると、すべてのGUIコンポーネントはWM_PAINT
、WM_KEYDOWN
などのキューに入れられたメッセージの受信を停止します。
3MBのテキストファイルをエディットコントロールに読み込んだときにアプリケーションがハングアップしているように見えます。そのファイルのサイズは私にとっては非常に大きいとは言えませんし、ロードをより良く行うエディットコントロールを見つけるのが一つの明白な解決策です。たとえば、Notepad、Notepad ++などは、そのようなファイルをロードするときに進捗状況を表示するような手順をとっていないと確信しています。私はむしろ、それらのアプリがファイルをロードするときにキューをポンピングしないと思っていますが、短時間のために気付かないだけです。
実行したくないのは、GUIを応答し続けるためにキューをポンピングし、最初のロード中に別のファイルのロードを開始できるようにすることです。ロード操作を処理している間はUIを無効にする必要があります。これを行うには、モーダルの進捗ダイアログが必要です。
パフォーマンスの良いコントロールに切り替えることができない場合は、モーダルプログレスダイアログを表示して、このようなバックグラウンドスレッドを使用できます。バックグラウンドスレッドは、ファイルを小さな塊(例えば、文字列リスト)にロードします。ファイルの各チャンクが準備完了したら、Synchronizeを呼び出してメインスレッドを取得して、文字列リストの内容をエディットコントロールに追加し、文字列リストを消去します。スレッドは、次に、次のチャンクをロードし続けます。小さな塊でエディットコントロールに追加すると、メッセージキューを保守することができます。
モーダルダイアログではなく、ステータスバーに進捗状況を表示することができます。しかし、リエントラント実行を引き起こすUIを無効にすることを忘れないでください。
Sleep()関数のDEFINITIONは「このスレッドをフリーズ」しています。メインスレッドをフリーズすると、すべてのフォームがメインスレッドからのみ機能するため、フリーズします。 win32アプリケーション設計におけるメッセージポンプの重要性を理解する必要があるように思えます。 http://en.wikipedia.org/wiki/Event_loop –
スリープを呼び出す本当の理由はありますか? –
フォアグラウンドスレッドですか?いいえ。また、バックグラウンドスレッドでも、WaitForSingleObjectはより良いでしょう。私はOPがSleep()を使って、3MBのテキストファイルがどれくらいの時間読み込まれたかを嘲笑していたと思う。 –