🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

1979閲覧

C#の別フォームへの(スレッドを使った)クローズ処理について

aikawajun

総合スコア14

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2021/03/25 04:39

編集2021/03/26 01:44

現在2画面作っており、一つはボタンを押すと選択されたエクセルを開く処理の画面とそのオープンの処理のに時間が掛かるため、プログレスバーの画面を作り、そちらを10秒を上限に更新していき、オープン処理が終わったら、Endと言うメソッドを呼び出して、プログレスバー側の画面のクローズ処理を行いたいと思っております。

Excel = new ExcelLiB(); _excelLoad = new FormExcelLoading(); _excelLoad.Show(); _excelLoad.Start(); // タイマーをスタートさせる処理で、タイマーの方でプログレスバーの値を1ずつ増やしています。 Excel.Open(path);//エクセルのオープン処理(ここで時間が掛かっているため画面が止まって見えています) _excelLoad.End();

一応、別にテストプロジェクトを作って、時間のかかるエクセルオープンの箇所をタイマーで10秒経ったら処理するようにして確認した上で、実際のエクセルオープンの箇所(上記※箇所)の前後に入れたところ、プログレスバーのメモリが動かず、エクセルが開いた後のEndメソッドにすぐ行ってしまう感じの動きでした。

動き的にThread.Sleep的な感じで止まっている様でしたので、

Thread thread = new Thread(new ThreadStart(() => { _form2 = new Form2(); _form2.Show(); _form2.Start(); })); thread.Start();

と言う風に別スレッドでフォームを開いたつもりで

※Excel.Open(path); thread = new Thread(new ThreadStart(() => { _form2.End(); })); thread.Start();

上記で閉じる処理を走らせようと思ったのですが、2~3時間調べながらやっているのですが、全く上手く行っておらず、どのようにした方が良いのか教えて頂けないでしょうか。

再度まとめると下記2点になります。
・エクセルのオープン処理時(Thread.Sleep的な止まっている間)に画面が止まるため、別フォームにプログレスバーを用意してそちらを表示。

・エクセルによって開くタイミングが違うため、そちらはタイマーを使っておおよそ15秒になったら目盛りが満タンになるようにして、エクセルのオープン処理が終わったらEndメソッドを使って、クローズ処理(プログレスバーの目盛りを最後まで行ったように見せて閉じる)を走らせる。

スレッドやタスククラスを使って簡単に出来るかと思ったのですが、全く前に進めておりません。
参考になるサイトでも構いませんので、教えて頂きたいです。

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/03/25 05:07

await Task.Run を使って Excel.Open(path) を UI スレッドとは別のスレッドで動かしたらどうなりますか?
aikawajun

2021/03/25 05:15

await Task.Runがどう違うのか分からないので、調べて確かめてみたいと思いますが、メイン(スレッド?)はExcel.Open(path)の方になるため、どちらかと言うとプログレスバーを後からくっつけており、別スレッドにしたいのは、プログレスバーの方になります。
aikawajun

2021/03/25 05:48

await Task.Runですと他に使っているExcel.Openの箇所も直す必要がありそうなため、とりあえずExcel.Openを別スレッドにしてみましたが、やはり結果としては、別フォームのプログレスバーのこうしんが行われることが無く、とりあえず初期値で半分ぐらいまでしてしまって、表示する他ないのかと悩んでいます。
退会済みユーザー

退会済みユーザー

2021/03/25 05:51

ちなみにExcelに対してどのような操作を行いたいのでしょう?Interop.Excelは非常に遅いので、ライブラリ変えるだけでそもそも待つ必要が無くなるかもしれませんが。 https://qiita.com/s_Pure/items/d92e5988d8207f5adb89
aikawajun

2021/03/25 06:06

ソースに記載してないのですが、 Excel = new ExcelLiB(); とオブジェクトを作っており、ExcelLiBと言うライブラリを使っております。 ライブラリ自体は拾ってきたもののため、使い方的にはオープンして、各シート名やシート内のセル情報を取得するために使っておりますが、中身に関しては、あまり詳しく見ていないのが現状です。 ファイルにもよりますが、少し重い(5MBくらい)のファイルを開こうとしているため、オープンに時間が掛かっていると思われますが、読み込んでいる際はやはりThread.Sleep的な感じで、別スレッドも止まってしまうのは仕方ない事でしょうか?
退会済みユーザー

退会済みユーザー

2021/03/25 06:26

> await Task.Runですと他に使っているExcel.Openの箇所も直す必要がありそうなため 直す必要は無くて、単に以下のようにすれば少なくとも UI スレッドがブロックされてフリーズしたようになるということはなさそうですけど。呼び出すメソッドに async キーワードを付ける必要はありますが「直す」というほどのものではないのでは? await Task.Run(() => Excel.Open(path));
退会済みユーザー

退会済みユーザー

2021/03/25 06:35 編集

> ソースに記載してないのですが、 > Excel = new ExcelLiB(); > とオブジェクトを作っており、ExcelLiBと言うライブラリを使っております。 外部ライブラリを既に使っているのであれば、それも質問に記入してください。 読込だけなら、ExcelDataReader が速いらしいですが。
退会済みユーザー

退会済みユーザー

2021/03/25 06:32

質問者さんの過去スレッドが全てクローズされてなくて放置状態です。クローズできるものはクローズしてください。
退会済みユーザー

退会済みユーザー

2021/03/25 06:36 編集

(コメント内容が被っていたので削除しました)
aikawajun

2021/03/25 06:40

ソースに記載しておらず失礼しました。 また、こちらも書いてなくて申し訳ないのですが、ロード時にエクセルをオープンして、フォームのクローズ時に一緒に処理する予定のため、オープンしたままの状態で問題ありません。
aikawajun

2021/03/25 07:44

すみません、今理解しました。 それぞれクローズしていきます。 失礼しました。
退会済みユーザー

退会済みユーザー

2021/03/25 08:36

上の 2021/03/25 15:26 の私のコメントで書いた件、試していただけたでしょうか? 結果をお知らせいただけると幸いです。
aikawajun

2021/03/25 08:43

すみません、試したところ、プログレスバーが上手く動きませんでした。 回答を頂けた方のやり方でForm2をusingで囲ってその中でエクセルをオープンしたところうまく行くようでした。
退会済みユーザー

退会済みユーザー

2021/03/25 09:33 編集

一番の問題は UI スレッドがブロックされてフリーズしたようになるということだと理解していますが、その問題は解決できたのでしょうか? であれば、プログレスバーの表示の方はその次の別の課題として考えればよさそうですけど?
aikawajun

2021/03/26 01:05

理解が浅いかもしれませんが、そのような形かと思います。 問題点としては、エクセルオープン時にフリーズ(Thread.Sleep的な感じで止まっている)しており、プログレスバーの目盛りがオープン処理が終わった後に進むと言う感じですので、突貫かも知れませんが、後々の不具合が無ければ、ほぼ解決したのかと思いますが、現状の処理で良いのか一抹の不安が残ってます。
guest

回答1

0

ベストアンサー

Form2にTimerを仕込んでProgressbar操作しているようなので、そっちはノータッチで
こんな感じでどうですか
asyncつけてあげるの忘れないように

using (var f = new Form2()) { f.Show(); await Task.Run(() => { // 重い処理 }); }

投稿2021/03/25 06:02

sinya0320

総合スコア211

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aikawajun

2021/03/25 06:07

ありがとうございます。 確認してみます!
aikawajun

2021/03/25 06:47 編集

テスト環境では大丈夫そうだったのですが、重い処理の部分が、今回はエクセルのオープン処理で、usingにしてしまうと、閉じてしまう可能性があると思いますが違いますでしょうか? オープン処理をそのフォームが閉じられるまでは開きっぱなしにしているため、部分的な動きはクリアできたのですが、その後の処理の部分で厳しそうです。。。
sinya0320

2021/03/25 06:34

ちょっと良くわかんない。 「// 重い処理」を「Excel.Open(path);」に置き換えるとして 「Excel.Open(path);」が完了するまではForm2は開きっぱなしになりませんか? 「Excel.Open(path);」だけでなく、その後の処理中もForm2を開きっぱなしにしたいのであれば 「// 重い処理」のところに追加するか、 メソッド化して切り出して、「// 重い処理」にそのメソッドを書いて下さい。 正確には違うはずですが、ニュアンス的に awaitは、その処理が終わるまでその場で待機して、終わってからその後を継続するので usingを抜けるのは、await Task.Run();の処理が終わった後ですよ。
退会済みユーザー

退会済みユーザー

2021/03/25 06:39 編集

そもそもExcelのインスタンスとForm2は関連が無いのであれば、usingでForm2が解放されても特に影響は無いと思われますが。
aikawajun

2021/03/25 08:19

確認してみたところ、私の知識不足でしたが、開いたエクセルが閉じると言う事はありませんでした。 多分問題ないかと思うのですが、エクセルが何らかの不具合を持っていて、オープンに失敗した時にusingを囲う形でtry-catchしているのですが、問題なくエクセルの不具合をキャッチできますでしょうか。 手元に、エクセルがおかしいものなどが無いため、確認出来ず分かれば教えて頂けないでしょうか。
退会済みユーザー

退会済みユーザー

2021/03/26 00:26

試しにExcelじゃないファイルを開いてみては。
aikawajun

2021/03/26 01:47

伝えずらいのですが、テキストボックスにドラッグアンドドロップしたファイルを入れるようにしており、パスから、エクセルじゃないファイルは、弾くようにしているため、エクセルじゃないファイルを開くことが出来ません。 あ、ですが、例えばテキストファイルの拡張子を.xlsx等に変えれば、キャッチできるかもしれないと思いましたので、一旦やってみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問