【解決は1000ポイント:C#のプロセス間処理2回目】


前回の質問の続きです。参考になる意見をいくつもいただいたのですが
解決に至らなかったのであらためて質問します。

前回の質問URL:http://q.hatena.ne.jp/1303911980


質問本文はコメント欄をご確認ください。

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2011/05/06 18:45:03
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答1件)

id:SweetSmile1978 No.1

回答回数199ベストアンサー獲得回数31

ポイント60pt

プロセス間ではなくてスレッド処理では?

バックグラウンド処理でプログレスバーの表示をさせているようですが、

UI関連は基本的にメインのスレッドでやった方がいいです。

プログレスバーをメインのスレッドで処理し、

肝心の処理をバックグラウンドで行ってはどうでしょうか?

id:harunoharuno

【C#について質問】

>>UI関連は基本的にメインのスレッドでやった方がいいです。

>>プログレスバーをメインのスレッドで処理し、

>>肝心の処理をバックグラウンドで行ってはどうでしょうか?

今後心がけますが、

すでに概ね汲みあがっているため

原因がわからない状態では修正にくい事情があります。

エラーが発生する原因についても示唆していただけると

うれしいのですが、、、、

2011/05/01 18:41:15
  • id:harunoharuno
     Form.csで計算処理を行います。
     その間、BackgroundWorkerでプログレスバーを表示しているんですが、この
     プログレスバーで問題が発生しています。
     
     Form.csで計算処理が完了したタイミングで、
     BackgroundWorkerが持つ、処理継続用のフラグをOFFにし、
     プログレスバーを終了します。
     
     プログレスバーは終了する直前に、プログレスバー表示フラグをOFFにしていることから、、、
     Form.csは処理再開まで以下のような待ち方をします


     ●Form.csのプログレスバー終了の待ち受け

      プログレスバー終了フラグ=true;    

      while(プログレスバー表示フラグ==true){

       log.write("注意:プログレスバー表示中");
       System.Windows.Forms.Application.DoEvents();
      }
      log.write("処理完了");


      質問者からみればこの待ち方にとくべつ問題はなさそうにみえるのですが、、、、プログレスバーを終了しても
      50%くらいでループから抜け出しません。
      
      なぜこのようなことがおこるのでしょうか?
      なお、、、、
      
      いまだに現象をつかみ切れていませんが、
      印象ではForm上に配置されているコントロール(DataGridView)のイベントに処理を横取りされ、Whileから
      抜けてしまうのではないかと思っています(見当違いがら指摘していただけると助かります。)。
      いろいろ想像し試してみていますが、、こんな現象は初めてです。アドバイスのほどよろしくお願いします。
  • id:heke2mee
    新しい質問のコメント欄が開いてなかったのでこちらに書きます。
    log.writeのメソッドはマルチスレッドに対応してるのでしょうか?

    ファイルへの出力ではなくSystem.Diagnostics.Debug.WriteLineに変更しても同じ現象が
    発生しますか?
  • id:harunoharuno
    回答ありがとうございます。
    ご指摘を受けて全てログを消しましたが、

    それでも本現象は発生するようです。

    なお、気が付いたことがありますので追記いたします。

     ・VisialC#2008からDebug実行した場合は、100%ループから抜けてくれるようです。なお、Debugモードでコンパイルし作成したExeファイルを実行した場合は、いままでの説明どおり80%くらいの確立でループから抜け出ることはありません。
     
  • id:sardine
    まったく試していないのでコメント欄で失礼します。

    複数スレッドから bool に読み書きすると聞いて、Double-checked locking イディオムを思い出しました。
    このイディオム自体はシングルトンの初期化に関するものなので、質問者さんに直接関係ないですが、
    よく言われることとして
    「あるスレッドから変数に書き込んでも、別のスレッドからは値が変わっていないように見えることがある。
     そのため、Double-checked locking を使うには、書き込んだ内容が別のスレッドにもちゃんと見えるように
     必要な手順を踏まないとダメだよ」
    というのがあります。

    で、必要な手順って何よ、という話になるわけですが、Wikipedia 英語版の記事
    <http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Microsoft_.NET_.28Visual_Basic.2C_C.23.29>
    によると、.NET の場合は、
    「System.Threading.Thread.MemoryBarrier() メソッドを使う」
    「変数に volatile キーワードを付ける」
    のどちらかをやればいいようです。

    質問者さんの場合で言うと、プログレスバー終了フラグの宣言に volatile を付けることで、
    スレッド間でメモリの読み書きが同期されるようになり、100%ループから抜けられるように
    なるのではないでしょうか。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません