アプリ版:「スタンプのみでお礼する」機能のリリースについて

OS:Windows2000
VB:VisualBasic6.0 ServicePack6
------------------------------

DoEventsに関しての質問です。

Winsock の SendProgress イベントで送信をキャンセルする時の為に DoEvents を
書いたところ、「スタック領域が不足しています」 とのエラーが出てしまいました。
*ヘルプには、DoEvents の呼び出しすぎと書いてありました。

DoEvents のかわりに、別の方法でキャンセルが出来るようにする事は可能でしょうか?

A 回答 (3件)

SendProgress イベントは、送信中に起動されるので、おそらくガンガンかかってしまい、ネストしまくってスタックオーバフローを起こしているような感じでは?



Winsockなら、パケット通信だと思いますので、「別の方法」といえばパケット間(SendComplete)でキャンセルするとか・・・
プログラムのつくり方にもよりますが、送信前にキャンセルされているかどうかをチェックできればそれがいいような気がします。

>送信をキャンセルする
パケット長は、数kBなので送信中(SendProgress)イベントでキャンセルするタイミングがあるかどうか、が問題ですね。

この回答への補足

Winsockだけでなく他の事(ファイル検索等)の再帰処理でも使いたいのですが、
APIやその他を使ってDoEventsと同じ事をさせる方法もあれば教えて頂けますでしょうか。
(コマンドボタンを押してコードが実行完了するまで、
 他のボタンが押せなくなってしまうのでそれを回避したい。)

補足日時:2004/09/13 22:37
    • good
    • 0
この回答へのお礼

アドバイスをどうもありがとうございます。
早速、参考にさせて頂きたいと思います。

お礼日時:2004/09/13 22:39

>再帰をして階層が深くなると同じようにスタック領域~のエラーが出るので、


>DoEvents が使えない

DoEvents が使えないわけではなく、DoEvents(Windowsのイベント処理)の中から、あなたのプログラムのイベントがガンガン起動されているからオーバーフローしているのだと思います。

つまり、該当のイベントがくるようなところでなければ、ネストは少なくてすみますから、DoEventsを書いても大丈夫です。

>再帰をして階層が深くなると・・・・

これは、次の再帰プログラムの原則を守れば大丈夫。もちろんDoEventsも使えます。
(1)極力スタック(引数やローカル変数など)を使用しない
(2)再帰の最大回数を制限(または予測)できる場合にのみ使用する

ただ、あくまで原則で、たとえばネット上のファイル検索で検索中にガンガンファイルコピーされて、
対象のファイルが増えてゆくなんて場合は、再帰の使用自体を考え直す必要があります。

今思いつく対策は、3つくらいかな。
(1)再入しないようなプログラムにする。イベントの初めに、イベント生起を止める。
  VBのTimerだと、Enable=False にするとかです。
  ただWinsock のように相手がある場合は、通信が変になるので使えないでしょうけど

(2)マルチスレッドにして、イベント処理レベルのルーチンを切り離す
 再帰は、上位のルーチンで使用します。
  http://www.int21.co.jp/pcdn/vb/noriolib/vbmag/99 …
 とか、
  http://homepage2.nifty.com/kasayan/vba/doevents. …
  あたりが参考になるかも・・

(3)OSのイベントをフックしたりマスクしたりして、ごまかす。
  今回、これは論外でしょうね。
 でも、Windows、MAC以外のOSをいじっているプログラマならかなり現実的な候補なんです。

#DOS時代からプログラムいじってますが、「スタックオーバーフロー」は、久しく見ていないので、懐かしく思いつつ・・・
    • good
    • 0
この回答へのお礼

お礼が遅れてしまい申し訳ありませんでした。
色々と参考にさせて頂きたいと思います。
どうもありがとうございました。

お礼日時:2004/09/22 10:07

>APIやその他を使ってDoEventsと同じ事をさせる方法もあれば教えて頂けますでしょうか。


そのための「DoEvents」なんですが・・・
API で実現する場合は、基本的には、C言語(しかもSDK)のようなメッセージループの中に書くか、コールバック関数を利用することになると思います。関数名としては、ほとんどがSendMessageA()なので、一般的な説明はしづらいです。

ご質問のようなエラーは、Winsock(のようなOCX)からコールバックされたイベントですから、その中でさらにDoEventsするのは、Winsockが動いてしまい危険。
VBのイベントは、Windows(やOCX)からコールバックされているので、できれば、その中にDoevents(Windowsの仕事をさせるようなこと)をさせないほうがいいです。

また、VBのDoEventsは、結構良くできていて、市販やフリーのCコンパイラでまじめに作るのと比べると、処理時間がかなり早い。
(多分Windowsでのタスク切り替えに不要な部分が大幅にカットされているんだと思います。M$だからできることですね)

モノにもよりますが、WinsockのSendProgress イベントには、せいぜい文字を点滅させるとか、カンタンで素早いプログラムにしたほうがいいと思います。

>(コマンドボタンを押してコードが実行完了するまで、
> 他のボタンが押せなくなってしまうのでそれを回避したい。)
「ファイルの検索」とかなら、VBのイベントを使わないでできるはずですから、DoEventsでOK。

この回答への補足

(これはWinsockの件ではなく)
再帰をして階層が深くなると同じようにスタック領域~のエラーが出るので、
DoEvents が使えない状態なので他の方法があるのかお聞きしました。

補足日時:2004/09/14 14:32
    • good
    • 0
この回答へのお礼

再度アドバイスを頂きどうもありがとうございます。

お礼日時:2004/09/14 14:32

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!