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

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

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

Re[4]: ファイル作成待ち処理


(過去ログ 101 を表示中)

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

■60616 / inTopicNo.1)  ファイル作成待ち処理
  
□投稿者/ kent (4回)-(2011/07/12(Tue) 21:02:49)

分類:[C#] 

2011/07/12(Tue) 21:04:08 編集(投稿者)

Visual Studio 2008 SP1 + Windows Form Application + C#です。

特定フォルダにある画像ファイルの一覧を、
サムネイルで表示するプログラムを作っています。

実際にはタイマーで特定フォルダを監視し、
フォルダ中にある画像ファイル群が更新されていたら、
サムネイルを作りなおすということを行っています。

Image.FromFile()メソッドでファイルの読み込みをしているのですが、
OutOfMemoryExceptionが発生するときがあります。
画像は大きくないので、メモリ不足ではありません。
デバッガを貼ったり、スリープを入れたりすると再現しないことから、
タイミング問題だと思われます。

書き込み途中のファイルを読み込んでしまって、
ファイルフォーマット不正ということで、
OutOfMemoryExceptionが起こると推測しています。
Image.FromFileは不正なフォーマットのファイルを読み込むと
OutOfMemoryExceptionを起こすようなので。

ファイル書き込み中は待つという方法で回避できるかと思うのですが、
どのような実装方法があるでしょうか?
引用返信 編集キー/
■60617 / inTopicNo.2)  Re[1]: ファイル作成待ち処理
□投稿者/ 魔界の仮面弁士 (2246回)-(2011/07/12(Tue) 21:14:55)
No60616 (kent さん) に返信
> Image.FromFile()メソッドでファイルの読み込みをしているのですが、
その Image をどの程度の期間保持するのかにもよりますが、
開いてすぐに閉じる運用では無いのなら、Image.FromFile よりも
Image.FromStream の方が良いと思います。
http://support.microsoft.com/kb/309482/

> ファイル書き込み中は待つという方法で回避できるかと思うのですが、
> どのような実装方法があるでしょうか?
たとえば、エラーになったら 0.5 秒後に再度開きなおしてみて、
それを 3 秒間繰り返してもエラーが回避できないなら、その画像は
[読み取りエラー]を表すような代替サムネイルとして表示させるとか。
引用返信 編集キー/
■60618 / inTopicNo.3)  Re[1]: ファイル作成待ち処理
□投稿者/ 逆運の覇者 (30回)-(2011/07/12(Tue) 21:19:29)
同期と非同期があります。
同期処理は処理が終わらないと次の処理ができません。
非同期処理は処理が終わるのを待たずに次の処理へ移行します。
kentさんが求めているのは同期関数です。
しかし、おそらくはすでに同期的にファイル書き込みをしているでしょうから、
問題はそこ以外ではないかと。

読み込むファイルは本当に正しいですか?
画像処理ソフトで普通に開くことができますか?

メモリの解放はしていますか?
画像1つのサイズは小さくとも、解放するべきところで解放せずにメモリリークを起こしていませんか?
引用返信 編集キー/
■60623 / inTopicNo.4)  Re[1]: ファイル作成待ち処理
□投稿者/ shu (843回)-(2011/07/12(Tue) 22:49:17)
No60616 (kent さん) に返信

FileSystemWatcherで作成、更新(削除も?)を監視しこれらのイベントが
発生したら処理候補リスト(Queueがいいかも)に対象ファイルを追加(削除)し
Timer発生時に処理を行うようにするとタイマ発生時に全ファイルの状態を
確認する必要がなくなるので処理を減らすことが出来ます。
あとは魔界の仮面弁士のレスにあるようにエラー時リトライで処理すると良いのでは
ないでしょうか?
引用返信 編集キー/
■60624 / inTopicNo.5)  Re[2]: ファイル作成待ち処理
□投稿者/ Azulean (781回)-(2011/07/12(Tue) 22:52:45)
2011/07/12(Tue) 23:30:15 編集(投稿者)

No60618 (逆運の覇者 さん) に返信
> しかし、おそらくはすでに同期的にファイル書き込みをしているでしょうから、
> 問題はそこ以外ではないかと。

自分のプロセスで画像ファイルを生成しているという前提は書かれていません。
逆に、「タイマーで監視してサムネイルを生成する」という記載があるので、別のプロセスがファイルを作成する可能性が高いのではないでしょうか?
その状況下で、「問題はそこ以外ではないかと」と判断するのは難しいと考えます。

(2011/07/12 23:30追記) ”そこではないかと”→”そこ以外ではないかと”に訂正。


> メモリの解放はしていますか?
> 画像1つのサイズは小さくとも、解放するべきところで解放せずにメモリリークを起こしていませんか?

GDI+ のエラーは結構いい加減です。
例外だけにとらわれていると本当の原因がつかめないこともあり得ます。


No60623 (shu さん) に返信
> FileSystemWatcherで作成、更新(削除も?)を監視しこれらのイベントが
> 発生したら処理候補リスト(Queueがいいかも)に対象ファイルを追加(削除)し
> Timer発生時に処理を行うようにするとタイマ発生時に全ファイルの状態を
> 確認する必要がなくなるので処理を減らすことが出来ます。

注意点としては、一回のファイル保存で複数回イベントが発生するという点です。
(タイマーから乗り換えれば OK ではないという部分を補足する意味合いで書いておきした)
引用返信 編集キー/
■60626 / inTopicNo.6)  Re[3]: ファイル作成待ち処理
□投稿者/ 魔界の仮面弁士 (2248回)-(2011/07/12(Tue) 23:24:07)
No60624 (Azulean さん) に返信
>>問題はそこ以外ではないかと。
> その状況下で、「問題はそこではないかと」と判断するのは難しいと考えます。
現段階では断定はできないという点で言えば、どちらの表現でも同じですが、
「そこ以外ではない」を「そこではない」にすると、意味が少々変わってしまう気が。

> GDI+ のエラーは結構いい加減です。
> 例外だけにとらわれていると本当の原因がつかめないこともあり得ます。
理由はともかく、「読み込みに失敗したのだろう」程度しか分からないかも知れませんね。


> ■No60623 (shu さん) に返信
>>FileSystemWatcherで作成、更新(削除も?)を監視しこれらのイベントが
FileSystemWatcherの参考例として。
http://www.atmarkit.co.jp/fdotnet/dotnettips/281filewatch/filewatch.html

> 注意点としては、一回のファイル保存で複数回イベントが発生するという点です。
取りこぼしが発生する事もあるのかも。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=35454&forum=7
http://hpcgi1.nifty.com/MADIA/Vcbbs/wwwlng.cgi?print+200904/09040001.txt
引用返信 編集キー/
■60627 / inTopicNo.7)  Re[4]: ファイル作成待ち処理
□投稿者/ Azulean (782回)-(2011/07/12(Tue) 23:31:57)
No60626 (魔界の仮面弁士 さん) に返信
> 「そこ以外ではない」を「そこではない」にすると、意味が少々変わってしまう気が。

ごっそり抜けていました。orz
訂正しておきました。ご指摘ありがとうございます。


> 取りこぼしが発生する事もあるのかも。

確かに重たい処理をしていると、取りこぼすことがあります。(メッセージあふれ?)
今回、画像をたくさん読み込んでサムネイルを作るという処理をする以上、うまく作らないと取りこぼしが起きそうですね。
引用返信 編集キー/
■60632 / inTopicNo.8)  Re[5]: ファイル作成待ち処理
□投稿者/ shu (844回)-(2011/07/13(Wed) 07:48:30)
> ■No60623 (shu さん) に返信
>>FileSystemWatcherで作成、更新(削除も?)を監視しこれらのイベントが
>>発生したら処理候補リスト(Queueがいいかも)に対象ファイルを追加(削除)し
>>Timer発生時に処理を行うようにするとタイマ発生時に全ファイルの状態を
>>確認する必要がなくなるので処理を減らすことが出来ます。
>
> 注意点としては、一回のファイル保存で複数回イベントが発生するという点です。
> (タイマーから乗り換えれば OK ではないという部分を補足する意味合いで書いておきした)
フォローありがとうmm


No60627 (Azulean さん) に返信
>
>>取りこぼしが発生する事もあるのかも。
>
> 確かに重たい処理をしていると、取りこぼすことがあります。(メッセージあふれ?)
> 今回、画像をたくさん読み込んでサムネイルを作るという処理をする以上、うまく作らないと取りこぼしが起きそうですね。
そうですね。そこでFileSystemWatcherでの処理はリストやキューへの追加、更新、削除だけということで提案してみました。
これでも取りこぼしが発生するほどファイルの書き換えが発生するのならTimerでの全件処理自体もきついのではないかと思われます。
取りこぼしがどうしても発生するようならFileSystemWatcherイベント発生時から連続発生するイベントがすべて終了したときに次の
Timerで現在の処理を行うというのはどうでしょう?終了タイミングのチェックが少し難しそうですが。

引用返信 編集キー/
■60638 / inTopicNo.9)  Re[2]: ファイル作成待ち処理
□投稿者/ kent (5回)-(2011/07/13(Wed) 10:52:57)
みなさん。色々と意見ありがとうございます。

別プロセスが任意のタイミングでImageMagickをコマンドライン起動し、
フォルダに画像ファイルを置きます。
そんなわけなので、いつファイルが追加されるか不明な状態です。

画像ファイルは開いてサムネイルを作成したら、すぐにDisposeする流れです。
Environment.WorkingSetでメモリの使用量を確認してますが、
メモリリークもありません。

作成された画像ファイルは再読み込みか、
別アプリで開くと問題ないので、
壊れたファイルというわけでもありません。


Image.FromStreamでファイル作成中のロック待ちを期待して、
ダメだったらリトライという方向性でやってみます。
引用返信 編集キー/
■60639 / inTopicNo.10)  Re[3]: ファイル作成待ち処理
□投稿者/ 魔界の仮面弁士 (2249回)-(2011/07/13(Wed) 11:03:39)
No60638 (kent さん) に返信
> 別プロセスが任意のタイミングでImageMagickをコマンドライン起動し、
> フォルダに画像ファイルを置きます。
> そんなわけなので、いつファイルが追加されるか不明な状態です。

書き込み中による問題を低減したいなら、ファイルを配置する側に
 1) 別の拡張子で配置(作成 or コピー)
 2) 配置完了後、正しい拡張子にリネーム
という形を取ってもらうのが安全かと思います。
別プロセス側に手を加えられるなら、ですけれども。
引用返信 編集キー/
■60643 / inTopicNo.11)  Re[4]: ファイル作成待ち処理
□投稿者/ kent (6回)-(2011/07/13(Wed) 11:53:56)
Image.FromStreamにしたらIOExceptionが上がってくるようになったので、
キャッチしてタイムアウト設定時間までリトライするようにしました。

ありがとうございます。
解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -