- ベストアンサー
VistaにおけるRAS API使用でフリーズ
- Vistaにて、RAS APIを使用する際にフリーズが発生する問題があります。
- RasGetEntryProperties()の呼び出し時に発生しており、原因は不明です。
- RAS APIを使用する際に注意が必要であり、詳細な情報が求められています。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
>なぜフリーズするのかの原因が分からない たぶん、Vistaで電話帳ファイルの管理方法が変わり、アクセス権の排他処理でデットロックするのが原因と思われます。 予測ですが、RasGetEntryProperties()で「書き換え中または使用中でロックされたエントリを読もうとした場合に、ロックが解除されるまで待つ」と言う事をしていて「誰もロックを解除してくれないので、永久に待っている」のだと思います。 こういうデットロックを防ぐ1番の方法は、 ・読み込み用エントリに対しては、読み込みだけ行う。書き込み等はしない ・書き込みしたエントリに対しては、読み込みや削除を行わない の2つです。 前回の回答では「接続を切ったら、4.でテンポラリの接続先を消す」と書きましたが、もし「テンポラリを残したままでも構わない」のなら「削除しない方が、削除するより安全」なので「4.では、何もしない」と言う手もあります。 但し、テンポラリを消さなくした場合は「1.の処理のRasSetEntryProperties()で、ロックされたテンポラリのエントリに上書きで書き込みをする可能性」があり、ロックされたエントリに対し上書きした場合の動作に不安が残るので、1.でデットロックが起きないか、充分に検証する必要があるでしょう。 >色々調べているときに、Sleep(5000)を入れたりしたのですが、5秒だとまだ足り >ないかもしれませんか? リファレンスにも -------- このような問題を回避する簡単な方法は、RasHangUp 関数を呼び出した後に Sleep(3000) を呼び出すか、RasGetConnectStatus 関数が ERROR_INVALID_HANDLE を返すまで RasGetConnectStatus(hrasconn) と Sleep(0) を交互に呼び出すループを記述することです。 -------- と書いてますので「Sleep(3000)」で充分だと思われます。
その他の回答 (1)
- chie65536(@chie65535)
- ベストアンサー率44% (8742/19840)
>1.の時にはこの現象は起きないのですが、4.の時に起きたり起きなかったりします。 だったら4.の処理をしなければ良い。 つまり1.の処理を 1)RasGetEntryProperties()で既存エントリから情報を取得する 2)電話番号の他に、エントリ名を「作業用接続先1」に書き替える 3)RasSetEntryProperties()で新規エントリを作成する に変え、4.の処理を 1)RasDeleteEntry()でエントリが「作業用接続先1」のエントリを削除 にします。 要は「電話番号を変えて接続したいなら、毎回、使い捨ての作業用接続先を作って、要らなくなったら破棄する」と言う事。 これなら「書き替えた電話番号を元に戻す必要がない」ので、余計な事はしなくて良いです。 なお、回線切断後、RasGetConnectStatus()で切断を確認した後は、Sleep()で「システムが電話帳の書き替えを行えるだけの、充分な待ち時間」を取ってから、次の処理に移行しましょう。 じゃないと4.の処理をRasSetEntryProperties()からRasDeleteEntry()に変えても、同様のハングアップが起きる可能性があります。
お礼
早速の回答ありがとうございます。 確かに、電話帳エントリを使いまわす必要はないですね。 書き換えることだけに頭が回って、テンポラリを作ることに気づけませんでした。 なぜフリーズするのかの原因が分からないのが気持ち悪いですが、今は安定 動作させるのが先決ですので、早速、頂いた方法で試してみたいと思います。 結果はまたご報告いたします。 >じゃないと4.の処理をRasSetEntryProperties()からRasDeleteEntry()に変えて >も、同様のハングアップが起きる可能性があります。 同じご経験があるのでしょうか? 色々調べているときに、Sleep(5000)を入れたりしたのですが、5秒だとまだ足り ないかもしれませんか?
お礼
その後の調査で、現象が起きる箇所を特定しました。 今回のプログラムでは、サブスレッドで受信処理をしているのですが、RAS切断後にこのスレッドを終了させており、スレッドが本当に終了する前に問題の処理を実行したときに発生しているようです。 今回の対応としましては、スレッド終了をWaitForSingleObject()で待ち合わせてから次の終了処理に移行するように修正することで、フリーズは起きなくなりました。 なぜフリーズしたのかの原因までは分かっていませんが、クローズさせていただきます。 ありがとうございました。
補足
フリーズの原因としては、そういうことが考えられるということですね。 これはもうMSに質問するしかなさそうなものなので、深追いはやめることにします。 >前回の回答では「接続を切ったら、4.でテンポラリの接続先を消す」と書きま >したが、もし「テンポラリを残したままでも構わない」のなら「削除しない方が >、削除するより安全」なので「4.では、何もしない」と言う手もあります。 ちょうど今、Vista環境にて動作確認を行っていました。 Vistaは新しい接続先に接続すると、その接続先がどのネットワークなのかを 選ばせるような画面が出てきてしまうので、毎回テンポラリを削除すると、通信 のたびにこの画面がでてきてしまうため、毎回テンポラリを削除する方法は 使えないです。 「4.では、なにもしない」にしてみて、デッドロック状態にならないかを確認して みたいと思います。