C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: Dir関数の解放が必要か


(過去ログ 137 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■80733 / inTopicNo.1)  Dir関数の解放が必要か
  
□投稿者/ あ (1回)-(2016/08/07(Sun) 09:21:54)

分類:[VB.NET/VB2005 以降] 


VBAではDir関数をforループで何度も使用する場合
Dir(vbNullString)
を使ってDir関数の解放を行ってやらないと
次に実行した時にエラーが出ることがあるのですが
VB.NETの場合にはこの操作は不要なのでしょうか?

上記を実行してもエラーが出て実行することができません。





引用返信 編集キー/
■80748 / inTopicNo.2)  Re[1]: Dir関数の解放が必要か
□投稿者/ 魔界の仮面弁士 (805回)-(2016/08/08(Mon) 12:13:04)
No80733 (あ さん) に返信
> VB.NETの場合にはこの操作は不要なのでしょうか?

VBA の物とは作りが異なるため、現在は不要になりました。
とはいえ、VB.NET で Dir を使うべきでは無いでしょう。
これは互換性を目的として用意されたものだからです。

今でも使えないわけでは無いのですが、処理効率や使い勝手を考慮すると
Microsoft.VisualBasic.FileSystem モジュールのメソッドの代わりに、
System.IO.DirectoryInfo クラスや My.Computer.FileSystem を
使うことをお奨めします。
(現在の Dir 実装は、内部で DirectoryInfo を呼び出しています)



ちなみに VBA 版の Dir は、列挙中にファイル数が増減した場合、
列挙される内容が動的に変化していくことになります。

それに対し、VB.NET 版では、引数付き Dir を呼び出した時点で
すべての列挙が完了しています。引数無し Dir は、その列挙済みの
バッファを順に読み出していく仕様であるため、列挙中に
ファイル数が増減した場合でも、増減前のファイル群が取得されます。



> VBAではDir関数をforループで何度も使用する場合

ご存知とは思いますが、一応おさらい。

Dir 検索を始めてしまうと、指定したパスに
探索すべきターゲットファイルが残っている間、
そのパスがロックされた状態になります。

引数付き Dir は FindFirstFile API
引数無し Dir は FindNextFile API の呼び出しなのですが、
内部的な検索ハンドルは一つしか持っていないため、
この関数は再帰的な読み出しでは使いにくいものになっていました。

そのため Office 2000 や VB5 以降では、FileSystemObject が
代わりに使われるようになりました。ただし、Dir の方が処理は高速なので
用途に応じて使い分けられていたようです。



> を使ってDir関数の解放を行ってやらないと

Dir の解放を行わないと、そのディレクトリがロックされた状態になり、
フォルダを削除できないなどといった問題が発生します。

特に、リムーバブルメディア(USB メモリーやフロッピーなど)の場合、
メディアのイジェクトを妨げる要因ともなりえます。

そのため、ロックを解除するために
 ・列挙完了まで読みきる
 ・別の場所を空読みする
といった対策が取られていました。


ロック解除のために「別の場所を空読みする」場合には、
たとえば Dir(Environment("WINDIR")) や Dir("NUL") が使われます。

実際には、影響を及ぼさない場所ならどのようなパスでも良いため、
Excel なら Application.Path、Access なら CodeDb.Name、
VB6 なら App.Path などを空読みしている例も見受けられますし、
Dir("C:\") のように固定パスが使われているケースもあります。


> Dir(vbNullString)
VB/VBA のバージョンにもよりますが、これ単体では、
対処コードしては、必ずしも適切では無いと思います。


というのも、Dir("") や Dir(vbNullString) という処理は、
Dir(CurDir()) と同じ意味になってしまうため、結果として
カレントディレクトリのロックを誘発してしまうためです。

そもそもカレントディレクトリというものは、それ自体が
ディレクトリをロックさせる要因になります。
(Dir を呼び出しかどうかとは無関係)

そのため、ロック回避のための対処コードとして
  Call ChDrive("C")
  Call ChDir("C:\")
  Call Dir(vbNullString)
などとすることがあるのですが、これをうっかり
  Call Dir(vbNullString)
  Call ChDrive("C")
  Call ChDir("C:\")
という順番にしてしまうと、むしろ問題を悪化させることになります。

これは、移動元のディレクトリ内に複数のファイルがあった場合に、
後者冒頭の Dir が、移動元のパスを列挙状態にしてしまうためです。
引用返信 編集キー/
■80750 / inTopicNo.3)  Re[2]: Dir関数の解放が必要か
□投稿者/ 魔界の仮面弁士 (807回)-(2016/08/08(Mon) 14:30:27)
No80748 (魔界の仮面弁士) に追記
> それに対し、VB.NET 版では、引数付き Dir を呼び出した時点で
> すべての列挙が完了しています。引数無し Dir は、その列挙済みの
> バッファを順に読み出していく仕様であるため、列挙中に
> ファイル数が増減した場合でも、増減前のファイル群が取得されます。

もしも動的な増減に対応した列挙が必要な場合は、
System.IO.Directory.EnumerateFileSystemEntries
というメソッドを使うことができます。(要VB2010以降)
引用返信 編集キー/
■80763 / inTopicNo.4)  Re[3]: Dir関数の解放が必要か
□投稿者/ あ (2回)-(2016/08/09(Tue) 22:12:48)
納得しました。
ありがとうございました。
 
引用返信 編集キー/
■80789 / inTopicNo.5)  Re[4]: Dir関数の解放が必要か
□投稿者/ あ (8回)-(2016/08/10(Wed) 21:45:22)
No80763 (あ さん) に返信
> 納得しました。
> ありがとうございました。
>  
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -