トップ回答者
ASP.NET Webフォームで長時間かかる処理の進捗を表示するには(async /await)

質問
-
Windowsフォームアプリケーションでは以下のようにして重い処理の進捗を表示できますが、同じことをWebフォームで実装するにはどうすればよいのでしょうか。
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private async void button1_Click(object sender, EventArgs e) { for (int i = 1; i <= 3; i++) { label1.Text = $"処理中({i}/3)"; await Task.Delay(5000); } label1.Text = "完了"; } }
試したこと
・Page1.aspxの先頭行にAsync="true"を追加
・Web.configの<configuration></configuration>の中に<appSettings><add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /></appSettings>を追加
・処理をPageAsyncTaskに書きRegisterAsyncTaskに登録
・書き換えるLabelをUpdatePanelの中にいれる
・ラベルのTextプロパティを変更した後にUpdatePanelのUpdateメソッドを実行する
これらを試したのですが、すべての処理が終わった後にラベルが更新される挙動になります。
よろしくお願いいたします。
回答
-
AJAX を使っての非同期処理(UpdatePanel も AJAX を使ってます)とサーバーにおける非同期プログラミングを混同しているのではないですか? async と await を使ってというのは後者(詳細は下記の記事参照)の話と思います。
ASP.NET の非同期/待機の概要
https://msdn.microsoft.com/ja-jp/magazine/dn802603.aspxScriptManager, UpdatePanel, UpdateProgress を使えば非同期要求をかけて応答が戻ってくるまでの間、サーバーで処理中という情報をユーザーに示すことはできます。具体的な方法は以下の記事を見てください。
UpdateProgress コントロールの概要
https://msdn.microsoft.com/ja-jp/library/bb386421.aspxしかしながらサーバーでの処置が何 % 終わったかというような進捗状況を表示することはできません。何故ならサーバーでの処理が終わるまでサーバーからは何の応答も返ってこないからです。
サーバーでの「重い処理」の実行中にその進捗状況をブラウザに表示するには、例えば、「重い処理」は別スレッドで処理するようにし、ブラウザからタイマーを使って定期的に AJAX で進捗状況をサーバーに問合せ、サーバーからその応答をもらって表示するというような処理が必要になります。
- 回答としてマーク M_Hashimoto 2015年12月30日 10:21
すべての返信
-
質問する際は、一番最初にご自分の環境(OS, .NET, IIS, Visual Studio のバージョン、DB サーバーとそのバージョン、ブラウザを使っているなら何かなど)を書いていただけませんか?
適切に情報が提供されていれば、回答者が質問者さんの状況を的確に把握でき、タイムリーで的を得た回答が得られるということで、質問者さんにもメリットがあります。ガイドラインも出ていますので目を通していただければと思います。
フォーラムのご利用方法(質問の投稿)について
https://social.msdn.microsoft.com/Forums/ja-JP/b2074c04-2e91-414d-8e9e-d634be311e31?forum=announcejaと注文をつけるばかりではなんですので・・・
> すべての処理が終わった後にラベルが更新される挙動になります。
質問者さんが書かれた Windows フォームアプリケーションでは全てがそれを起動したローカルの PC で動いていると思いますが、Web アプリケーションはそうではないということは理解されているでしょうか?
ユーザーがブラウザから Web サーバーに要求をかけると、全ての処置は要求を受けた Web サーバーで行われ、その結果が html, css, クライアントスクリプトとしてブラウザに送信され、ユーザーが見ているのはその結果だけになるはずです。
なので、そういうこと(すべての処理が終わった後にラベルが更新される)になるのだと思いますが・・・
サーバー側で起こっていることとクライアント側で起こっていることを区別して考えてみませんか? それを常に意識して開発しないと、今後いろいろ苦労が絶えないと思います。
- 編集済み SurferOnWww 2015年12月27日 11:31 一部訂正
-
ご返信ありがとうございます。
申し訳ございません、遅ればせながら環境について書かせていただきます。
Windows10Pro(64bit)
.NET Framework4.5.2
Visual Studio Community 2015
Internet Explorer 11
>>Web アプリケーションはそうではないということは理解されているでしょうか?
はい、そうでないことはわかっていますが、詳しく説明できるほどの知識はありませんでした。
私としては、普通に書いたのであればそういう動きをするのだろう、しかしUpdateパネルや非同期処理の構文を使ったのであれば、また違った動きをしてくれるのではないか、という程度の知識でした。
ASP.NET Webフォームの、あたかもデスクトップアプリのように開発できる、という点を曲解してしまったようです。
指摘していただいたように、サーバー/クライアントを分けた考え方を学ぼうと思います。
そして、なぜこれで動かないのか、というような質問になってしまいましたが、あくまでも題名の通り、長時間かかる処理の進捗を表示するにはどうすればよいか、ということですので、特定の書き方に縛られずどういった方法があるのか広く回答を頂ければ幸いです。
-
AJAX を使っての非同期処理(UpdatePanel も AJAX を使ってます)とサーバーにおける非同期プログラミングを混同しているのではないですか? async と await を使ってというのは後者(詳細は下記の記事参照)の話と思います。
ASP.NET の非同期/待機の概要
https://msdn.microsoft.com/ja-jp/magazine/dn802603.aspxScriptManager, UpdatePanel, UpdateProgress を使えば非同期要求をかけて応答が戻ってくるまでの間、サーバーで処理中という情報をユーザーに示すことはできます。具体的な方法は以下の記事を見てください。
UpdateProgress コントロールの概要
https://msdn.microsoft.com/ja-jp/library/bb386421.aspxしかしながらサーバーでの処置が何 % 終わったかというような進捗状況を表示することはできません。何故ならサーバーでの処理が終わるまでサーバーからは何の応答も返ってこないからです。
サーバーでの「重い処理」の実行中にその進捗状況をブラウザに表示するには、例えば、「重い処理」は別スレッドで処理するようにし、ブラウザからタイマーを使って定期的に AJAX で進捗状況をサーバーに問合せ、サーバーからその応答をもらって表示するというような処理が必要になります。
- 回答としてマーク M_Hashimoto 2015年12月30日 10:21
-
ご返信ありがとうございます。
教えていただいた通り、AJAXで定期的に進捗状況を確認しに行く、という方法で期待通りの動作をしました。
ASP.NET WEBフォームでの開発をあきらめ、サーバー側をASP.NET WebAPIで開発し、クライアント側はhtmlとTypeScript(JavaScript)+JQueryで開発しました。
自分の思った通りの実装ができ、たいへん感謝しています。
Webフォームでの実装はできませんでしたが、結果的にWeb寄りの実装方法を知ることができました。
本当にありがとうございました。
- 編集済み M_Hashimoto 2015年12月30日 10:28
-
> ASP.NET WEBフォームでの開発をあきらめ、
ASP.NET Web フォームアプリでも、できないことはないですよ。
- 編集済み SurferOnWww 2015年12月31日 1:39 引用追加