- PR -

イベントが頻発するようなWindowsアプリケーションの挙動について

投稿者投稿内容
JK
会議室デビュー日: 2005/08/11
投稿数: 10
投稿日時: 2005-08-19 10:17
WindowsアプリケーションでGUIクライアントを作成しています。

サーバではデータが逐次更新されており、クライアントで更新データを
リアルタイムで受信します。データの受信はイベントとして行い、この
イベント処理で画面に表示するデータを更新します。

サーバでのデータ更新頻度が増加すると、それに伴いクライアントでの
イベント処理の頻度も増加しますが、これが高じると以下のような現象が
発生します。

(第一段階)イベント処理は行われるものの、クライアントが描画されなくなる。
      タスクバーをクリックしてもウィンドウが表示されない。

(第二段階)イベントがそのものが発生しなくなる(イベントハンドラが
      呼ばれない?)。

このような現象について次のような疑問があります。

・一般的にイベント頻度が増加すると(第一段階)のようにイベント処理は
 行われるものの描画に影響が出る、といった挙動になるものでしょうか?
 それとも今回のようなケースはWindowsアプリケーションの実装に問題が
 ありそうでしょうか?

・このような現象を回避する標準的な方法はありますか? イベント処理の
 非同期化などを行うのでしょうか?

以上、よろしくお願いします。
Lichtenstein
ベテラン
会議室デビュー日: 2003/11/06
投稿数: 61
投稿日時: 2005-08-19 12:08
>一般的にイベント頻度が増加すると(第一段階)のようにイベント処理は
>行われるものの描画に影響が出る、といった挙動になるものでしょうか?
>それとも今回のようなケースはWindowsアプリケーションの実装に問題が
>ありそうでしょうか?

自分の非力なマシンの場合、すべからく描画に影響が出ているのですが(笑)
そういう症状とは違うのでしょうか?
CPUやメモリの使用率に問題があるかもしれません。

イベント処理に時間がかかる場合、その間画面が更新されなくなるような
アプリはよく作られますが、それに該当する可能性もあります。

>イベントがそのものが発生しなくなる(イベントハンドラが
>呼ばれない?)。

こういうのはキツイですね。ソケットが受信状態になるイベントを
なんらかの方法で登録しているのでしょうか?

一番手堅いのは、selectとWSAEWOULDBLOCKで非同期ソケットを扱うことです。
それ以外の方法では、利用しているライブラリ関数がエラーを返していないか、
神経質になる必要があります。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-08-19 12:54
引用:

一般的にイベント頻度が増加すると(第一段階)のようにイベント処理は
行われるものの描画に影響が出る、といった挙動になるものでしょうか?
それとも今回のようなケースはWindowsアプリケーションの実装に問題が
ありそうでしょうか?


あんまり頻繁になってくると、描画関係のメッセージが処理されないからですよね。
OS 側に処理を委譲させるタイミングを設けないといけないと思います。
(そういう意味ではない... ですか?)

引用:

イベントがそのものが発生しなくなる(イベントハンドラが呼ばれない?)


いわゆる、Busy な状態になって処理を受け付けなくなってるような気がします。
こういう場合は、頻度を減らすなどして、クリティカルな原因を掴むところから開始しましょう。



_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
JK
会議室デビュー日: 2005/08/11
投稿数: 10
投稿日時: 2005-08-19 13:01
回答ありがとうございます。

> 自分の非力なマシンの場合、すべからく描画に影響が出ているのですが(笑)
> そういう症状とは違うのでしょうか?
> CPUやメモリの使用率に問題があるかもしれません。

開発機のCPUはペンティアム4の1.7G、メモリは512Mですので、これ自体は
非力ではないですが、今回のサーバから要求される処理能力としては
非力かもしれません。私が作成したクライアントを他のマシンで実行したら
前述の現象は発生しなかったという報告も受けております。

ただ私はWindowsアプリの知見があまりないので、マシンが非力な場合の
典型的な症状をよく分かっていないのです。

> こういうのはキツイですね。ソケットが受信状態になるイベントを
> なんらかの方法で登録しているのでしょうか?

既存の通信ライブラリを使用しておりますので、通信部分の実装は
よく分かりません。ライブラリに用意されているイベントハンドラ
のデリゲート先を実装しているだけになります。

ちなみにこの実装ではDataGrid+カスタムDatasetでデータを画面に
表示させていますが、これらのコントロールを操作する部分の実装を
コメントアウトすると、前述の現象は発生しなくなります。

単純にデータを表形式で表示させるにはDataGrid+Datasetは重い
のかもしれません。
JK
会議室デビュー日: 2005/08/11
投稿数: 10
投稿日時: 2005-08-19 13:19
引用:

あんまり頻繁になってくると、描画関係のメッセージが処理されないからですよね。
OS 側に処理を委譲させるタイミングを設けないといけないと思います。
(そういう意味ではない... ですか?)



そういう意味だと思います。
イベント処理を一時停止して、フォームの描画を行わせるような
コードを書くべきでしょうか?例えばイベント処理の再度でRefresh()を呼んだり
したら、これはこれで重そうですが(^^;

何か典型的なパターンなどありますでしょうか。

引用:

いわゆる、Busy な状態になって処理を受け付けなくなってるような気がします。
こういう場合は、頻度を減らすなどして、クリティカルな原因を掴むところから開始しましょう。



頻度を減らした場合はきちんと描画できています。ただし想定しうる最大頻度までは
テストが必要でして、今回描画不能となった頻度も本番での想定内なのです。

# 最初の投稿で書き忘れてしまいましたが、サーバからの更新データをイベント引数で
# 受け取り、それをDatasetに詰めた上でDataGridで表示させています。
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2005-08-19 13:36
JKさん、こんにちは。

引用:

何か典型的なパターンなどありますでしょうか。


System.Windows.Forms.Application.DoEvents メソッド を適宜呼び出す、とか…?

引用:

よく分かりません。ライブラリに用意されているイベントハンドラ
のデリゲート先を実装しているだけになります。


以下、適当な事を言いますが、イベントハンドラでは実際の処理をせずに、「イベントが発生したよ」というフラグを立てといて、別のタイミングで定期的にそのフラグを見に行って処理を行うとか。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2005-08-19 13:56
unibon です。こんにちわ。

引用:

JKさんの書き込み (2005-08-19 10:17) より:
・一般的にイベント頻度が増加すると(第一段階)のようにイベント処理は
 行われるものの描画に影響が出る、といった挙動になるものでしょうか?
 それとも今回のようなケースはWindowsアプリケーションの実装に問題が
 ありそうでしょうか?

・このような現象を回避する標準的な方法はありますか? イベント処理の
 非同期化などを行うのでしょうか?


一般に、負荷が高いからと言って、描画がされないということはありません。たとえば、もし、マルチスレッドでなければ、描画以外の処理中はたしかに描画は滞りますが、でも時間が経過してその処理が終れば描画は問題なくなされるはずです。
同様に、イベントもいくら頻発しても、後から発生したイベントの処理は、それ以前に発生したイベントの処理が終るまで待たされますが、でも時間が経って以前のイベントの処理が終れば、順番に次のイベントが処理されるはずです。
もっとも、描画も含めて、イベントが頻発すれば、いわゆるバックログが溜まり、自転車操業になり破綻はします。しかし、この場合は CPU 使用率が 100%になるので区別がつきます。CPU が休んでいる時があるのに描画やイベント処理がされないなら、それはなにか(アプリケーションやミドルウェアやビデオドライバーや Windows 等)のバグでしかありません。

#もっとも、以上は理想論ですので、実際にはなにか泥臭いことで対処したりすることもありますが。
JK
会議室デビュー日: 2005/08/11
投稿数: 10
投稿日時: 2005-08-19 14:21
きくちゃんさん

引用:

System.Windows.Forms.Application.DoEvents メソッド を適宜呼び出す、とか…?


こちらを試してみましたが、今回の場合はうまくいかないようです
(想定外の例外がthrowされます)

引用:

以下、適当な事を言いますが、イベントハンドラでは実際の処理をせずに、
「イベントが発生したよ」というフラグを立てといて、別のタイミングで定期的に
そのフラグを見に行って処理を行うとか。


要件としてリアルタイムにデータの更新を視覚化する、というのがあります
のでこの方式は採用できないです。こちらの説明が足りませんでしたm(_ _)m

unibonさん

引用:

もっとも、描画も含めて、イベントが頻発すれば、いわゆるバックログが溜まり、
自転車操業になり破綻はします。しかし、この場合は CPU 使用率が 100%になるので
区別がつきます。


CPU利用率は100%ではないですね。ということはアプリ側の問題ということに
なるでしょうか。

今回私が行っている実装自体は特殊なことは行っておりません。
よって既存の通信ライブラリ(*.ocx)が怪しく思えてきました...

スキルアップ/キャリアアップ(JOB@IT)