ProgressBarの使い方で?

解決


マグ  2004-08-12 20:54:31  No: 115546

Form1からForm2をshowdialogで開いたときと同じ状態にしたいのですが、
そのまま  showdialogでForm2を開いたら、Form1の処理が止まってしまいます。
Form1の処理を止めないで、showdialogと同じ状態でForm2を表示させるにはどうすればいいでしょうか?


特攻隊長まるるう  2004-08-17 01:58:49  No: 115547

…?やりたい事は十分つかめてませんが…
 Form2.Show()
でどうにかしてみるとか?

System.Threading.Thread でマルチスレッド操作してみるとか?


マグ  2004-08-17 04:20:59  No: 115548

Form1内でSystem.Threading.Threadを使う方法は知っているのですが、

Form1で処理を行いながら、
Form2でSystem.Threading.Threadを使い、Form1での値を受け取り、
その値を使って、ProgressBarを動かすにはどうしたらよいでしょうか?


特攻隊長まるるう  2004-08-17 18:35:45  No: 115549

>Form1で処理を行いながら、
>Form2でSystem.Threading.Threadを使い、Form1での値を受け取り、
>その値を使って、ProgressBarを動かすにはどうしたらよいでしょうか?
それを考え出すのがマグさんのお仕事です。全く想像できないようなものは
プログラムは作成できません。しかし、動作を説明できているのですから、
処理を分解して考え、順を追って工夫していけばできるんじゃないですか?。
今回の場合、まず
1、Form1 で処理を行いながら、System.Threading.Thread を使い Form2 を表示する。
2、System.Threading.Thread で実行中の Form2 に Form1での値を渡す。
3、その値を使って、ProgressBarを動かす。
といった所でしょうか?。

>Form1内でSystem.Threading.Threadを使う方法は知っているのですが、
Form2 を New するのは Form1 ででしょうし、Form2 は参照変数として
処理するんでしょ?だったら普通の変数と扱いは変わらないんじゃないですか?
マグさんの知ってる方法で十分にできそうな気がしますが??


中年プログラマ  2004-08-17 19:10:53  No: 115550

> そのまま  showdialogでForm2を開いたら、Form1の処理が止まってしまいます。
子画面をモーダルではなく、モードレスにて表示する方向で考えてみては?
または、Form1が処理して、Form1自身に表示させるというスタイルを変更して、処理をForm2(または別のクラス)が行うようにして、それをForm1に表示させるとか。

マグさんが各フォームで行っている処理がわからないので、回答しずらいのですが
.NET で、非同期プログラムを行うとなれば、こんなパターンがあります。

(1) BeginInvoke/EndInvokeを使う。
(2) IAsyncResult.IsCompletedをポーリングして完了チェック。
(3) BeginInvoke/WaitHandle/EndInvokeを使ってIAsyncResultを待機。
(4) デリゲートを渡して、コールバックしてもらう。

> 2、System.Threading.Thread で実行中の Form2 に Form1での値を渡す。
あれ。それってOKなんでしたっけ?
.NETの Windows フォームやコントロールは「スレッドセーフ」では無いので、独自作成のスレッドの中から、Windows.Forms のコントロールにアクセスするわけにはいかない、と理解していたのですが。


特攻隊長まるるう  2004-08-17 20:10:45  No: 115551

>> 2、System.Threading.Thread で実行中の Form2 に Form1での値を渡す。
>あれ。それってOKなんでしたっけ?
>.NETの Windows フォームやコントロールは「スレッドセーフ」では無いので、独自作成のスレッドの中から、
>Windows.Forms のコントロールにアクセスするわけにはいかない、と理解していたのですが。
それは多分…正しいと思います。
[マルチスレッド : 同期クラスの使用法]
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vccore/html/_core_multithreading.3a_.how_to_use_the_synchronization_classes.asp
[スレッド処理のデザイン ガイドライン]
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpgenref/html/cpconthreadingdesignguidelines.asp
>インスタンス状態はスレッド セーフである必要がありません。既定では、クラス ライブラリはスレッド セーフではないことが必要です。
などの記述もあります。

スレッドセーフが重要なことは理解しているつもりですが、マルチスレッドは嫌って
使ってこなかったので(苦笑)不十分な点は多々あると思われます。ご指摘ありがとう
ございます。表現としても誤解を生みそうな回答ですよね。…訂正しようと思いましたが
上手い表現が見つかりませんでしたのでフォローできる方がいらっしゃいましたら
お願いします。
ただ、参照変数から Form クラスの関数などを利用する事は可能と思われます。
1、グローバルな参照変数(Form1 で有効なローカル変数)に Form2 のインスタンスを生成します。
2、スレッドで行うのはグローバルな Form2 の参照変数にアクセスして関数の実行などのみとします。
3、当初の質問で ShowDialog の状態を利用したいような書込みでしたので、スレッドは1つのみ起動するように
[VB.NET]
        Dim t As New Thread(AddressOf ThreadProc)
        With t
            If .IsAlive Then
                .Abort()
            End If
        End With
の処理を ShowDialog が解除された時点で適用しスレッドを殺してます。
4、Shared 宣言や参照変数のインスタンスが生成されているかを判断して 使用する Form2 のインスタンスは1つとします。

というような処理でそれなりに動くのは確認してます。…まぁ、処理として不安の
残る出来上がりなのでソースは公開したくないですし、
>子画面をモーダルではなく、モードレスにて表示する方向で考えてみては?
ボクもそっちの方がいいとは思ってますが…。…挑戦的な意味もこめてマルチスレッドの方向で回答をしようかと。


マグ  2004-08-17 21:22:41  No: 115552

ありがとうございました。

特攻隊長まるるうさんの言うとおり

スレッドで出来ました。
でも、多少、処理は遅くなります。


Dental  2004-08-17 21:54:38  No: 115553

話題が脱線しかけていますが、一応補足を。

例えば、グローバル変数を作って、複数のスレッドから
その変数にアクセスするのは、基本的に NG です。
それこそ、
  myVar = myVar + 1
という単純なコードでさえ、「同時に実行」された時に問題になります。

(1) Thread1 が、変数 myVar の値を読む。
(2) (OS が)Thread1 を中断し、Thread2 を実行させる。
(3) Thread2 が、先の myVar の値を読む。
(4) Thread2 は、その値に1を加算して、myVar に格納する。
(5) Thread2 が中断され、Thread1 が再開。
(6) Thread1 も、先ほど読み取った値に 1 を加算して格納。

# 何が問題になっているかわかりますか?

上記のパターンで、myVar の値が 10 だったとします。
この時、(1) の段階で Thread1 に取得された値も、「10」です。
その後、(3) の段階で Thread2 に取得された値も、「10」です。
そして、(4) にて Thread2 は、myVar を「11」に更新します。
最後に、(6) にて Thread1 も、myVar を「11」に更新します。

Thread1 と Thread2 が、それぞれ1回ずつ(計2回)処理したのに、
増加した値は +2 ではなく、+1 になってしまうわけです。

# マルチスレッドプログラムで厄介なのは、こうした同時実行に関する
# 問題が発覚し難い(再現性が低い)事にあります。

このような問題を回避するためには、

(方法0) マルチスレッド化を諦める。

(方法1) そもそもグローバル変数を使わない。

(方法2) グローバル変数を使うにしても、1変数につき1スレッドだけが
        アクセスする事にしておく。

(方法3) 複数のスレッドからアクセスしたいなら、何らかの「同期化」の
        手法を用いて、複数のスレッドからアクセスできないようにする。

などの回避策が必要です。


マグ  2004-08-18 20:35:00  No: 115554

なるほど。
スレッドを中断してたんですね。
道理で動きがおかしかったハズですね。←動いて止まって動いて止まっての連続でカウンターが増えていきました。
では、どのように記述すればいいか分かりません。
教えてください。
お願いします。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加