環境
Delphi:4
OS:Windows7 64bit
ソースは長くなってしまうため最後に記載させて頂きます。
1.最後に記載したソースの以下のループ時にフォームをクリックしたりアクティブ⇔非アクティブを繰り返すと応答なしになってしまいます。
たまに何もしなくても途中でフォームの%ゲージが止まってしまいます。
(どの状態でも内部では処理されているようで、CSV出力が終われば正常通り動くようになりCSVファイルも保存されています。)
この応答なし状態を回避したいのですが、何か方法はあるでしょうか?
具体的にはプログレスバーの更新は最優先で、その他機能フォームの移動、最小化などは制限してしまってもいいと考えています。
          for I := 1 to Parts.RecordCount do
          begin
            if PartsSUURYOU.Value then
              SaveToCSVFileAll(slCSV, sFileName, StartDate, Header);
            Parts.Next;
            Gauge1.ProGress := I;
          end;
以下がボタンクリック時の動作です。
procedure TMotocho2Form.FncBtn12Click(Sender: TObject);
var
  StartDate: TDateTime;
  Year, Month: Word;
  sFileName, Header: String;
  ans, I: Integer;
  slCSV: TStringList;
begin
  ans := Application.MessageBox('全品目の元帳を出力します。',
                                '品目別元帳', mb_OKCancel);
  if ans = IDOK then
  begin
    if FncBtn12.Enabled then
    begin
      Year := SpinEdit1.Value;
      Month := SpinEdit2.Value;
      StartDate := EncodeDate(Year, Month, 1);
      Header := '日,品目名,単価,入庫数量,出庫数量,在庫数量';
      sFileName := 'HINMOKUBALL' +FormatDateTime('yyyymm', StartDate)+'.CSV';
      SaveDialog1.FileName := sFileName;
      if SaveDialog1.Execute then
      begin
        slCSV := TStringList.Create;
        sFileName := SaveDialog1.FileName;
        Screen.Cursor := crHourglass;
        SetPrintEnabled(False);
        Gauge1.MaxValue := Parts.RecordCount;
        Gauge1.Visible := True;
        Gauge1.ProGress := 0;
        Gauge1.Update;
        Parts.DisableControls;
        Parts.First;
        StatusLine.Caption := '  出力中';
        StatusLine.Update;
        try
          for I := 1 to Parts.RecordCount do
          begin
            if PartsSUURYOU.Value then
              SaveToCSVFileAll(slCSV, sFileName, StartDate, Header);
            Parts.Next;
            Gauge1.ProGress := I;
          end;
          slCSV.SaveToFile(sFileName);
        finally
          Parts.First;
          Parts.EnableControls;
          Screen.Cursor := crDefault;
          SaveDialog1.InitialDir := ExtractFilePath(ExpandFileName(sFileName));
          SetPrintEnabled(True);
          Gauge1.Visible := False;
          SpinEdit2.SetFocus;
          EditEnter(SpinEdit2);
          slCSV.Free;
        end;
      end;
    end;
  end;
end;
※SaveToCSVFileAllではデータベースから該当するデータを順次slCSV.ADDしています。
長くなってしまい申し訳ありませんが、よろしくお願いします。
Application.ProcessMessagesを使えば
きっと応答無しにはならないでしょう
設計自体を改善すべきかと思いますが
とりあえずこんな感じでいかがでしょうか?
          for I := 1 to Parts.RecordCount do
          begin
            if PartsSUURYOU.Value then
              SaveToCSVFileAll(slCSV, sFileName, StartDate, Header);
            Parts.Next;
            Gauge1.ProGress := I;
            if I mod 100 = 0 then begin            // 100回に1回だけ処理
              Application.ProcessMessages();   // OSに処理を戻す
            end;
          end;
ちょっとややこしいですが、TThread を使えば完璧にできます。
ループ部分をTThread で実行して、メイン部分からコントロールすればOK
今回の問題にただちに応用するかは別として,
>ちょっとややこしいですが、TThread を使えば完璧にできます。
というレスがあったので.
例えば,以下を今後の参考にされてはいかがでしょうか.
http://edn.embarcadero.com/article/images/40483/2C.pdf
http://edn.embarcadero.com/article/images/40483/2C.pdf
ちなみに,こういった資料は,以下から閲覧またはダウンロードできます.
[とりあえず、デベロッパーキャンプの資料を読んでみようか。]
http://ht-deko.minim.ne.jp/tech044.html
>takeさん,HOtaさん,Mr.XRAYさん
ありがとうございます。
マルチスレッドを使用すれば理想通りの動きが行えそうです。
とりあえずApplication.ProcessMessagesを使用して動作を確認し
TThreadの使い方について勉強しようと思います。
Application.ProcessMessages();
を使用することで応答なしを回避できました。
今回はループするごとに毎回呼び出すようにしました。
しかしApplication.ProcessMessages();には
全てのメッセージを処理してしまうなどの問題もあるとのことなので
マルチスレッドについて勉強していこうと思います。
ありがとうございました。
Application.ProcessMessages();
を使用することで応答なしを回避できました。
今回はループするごとに毎回呼び出すようにしました。
しかしApplication.ProcessMessages();には
全てのメッセージを処理してしまうなどの問題もあるとのことなので
マルチスレッドについて勉強していこうと思います。
ありがとうございました。
| ツイート | 
        
         |