- PR -

複数のプロセスからのファイル処理

投稿者投稿内容
がらす
ベテラン
会議室デビュー日: 2005/07/14
投稿数: 99
投稿日時: 2008-09-03 04:11
ひとつのプロセスからファイルを書き込み、もうひとつのプロセスからそれに応じて(FileSystemWatcher を使用)ファイルを読み出そうとしています。

同じプロセス内なら lock を使えば簡単なのですが、違うプロセス間で排他処理をどのようにするのかで悩んでいます。ためしに何もせずに実行してみたら、やはり「他のプロセスで使われているのでアクセスできない」という例外が発生しました。

File, FileInfo, FileStream クラスなど調べてみたのですが、現在他のプロセスで使われているかを調べる方法が分かりませんでした。

何かいい方法は無いでしょうか。よろしくお願いします。
未記入
大ベテラン
会議室デビュー日: 2006/05/19
投稿数: 125
投稿日時: 2008-09-03 08:45
http://www.atmarkit.co.jp/fdotnet/dotnettips/707shareread/shareread.html
がらす
ベテラン
会議室デビュー日: 2005/07/14
投稿数: 99
投稿日時: 2008-09-03 09:25
未記入さん、どうもありがとうございます。

FileShareで例外を出さないようには出来るのですが、今度はファイルを読み込んだ後のデータが壊れているという事態が発生します。Write途中にReadしたりすれば、まあ当然なのですが…。

Write途中の場合には別プロセスのReadを待ってもらうにはどうすればいいのでしょうか?Semaphoreを使ってみているのですが、どうも上手く行きません。

・以下の方法で間違っているところがあれば、指摘していただけるとありがたいです。
・他にもっといい方法があるならば、教えていただけると幸いです。

どうぞよろしくお願いします。

コード:
m_writeSemaphore = new Semaphore(1, 1, readSemaphoreName);
//別のプロセスでは Semaphore.OpenExisting(readSemaphoreName) を使用

try
{
    m_writeSemaphore.WaitOne();

    XmlSerializer serializer = new XmlSerializer(typeof(Parameters));
    using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
    {
        serializer.Serialize(stream, sourceObj);
    }
}
catch (Exception ex)
{
 // 例外処理
}
finally
{
    m_writeSemaphore.Release();
}

Tram
常連さん
会議室デビュー日: 2002/10/10
投稿数: 21
お住まい・勤務地: 横浜
投稿日時: 2008-09-03 11:59
Mutexを使われてみてはいかがでしょうか。
http://msdn.microsoft.com/ja-jp/library/system.threading.mutex(VS.80).aspx
タコツボ
常連さん
会議室デビュー日: 2004/01/20
投稿数: 22
お住まい・勤務地: 京都・大阪
投稿日時: 2008-09-03 12:47
もしかして、書き込みするプロセスと、参照するプロセスが別のマシンで動いている、
ということはないですよね?
(別マシンであれば、SemaphoreやMutexは使えません)

以前、サーバの共有フォルダに別マシンからファイルをコピーしたり、FTPで
アップロードされてきたりするのを監視する仕掛けを作ったことがあります。

その時は、監視側ではファイルを開こうとして「他のプロセスで使われているので
アクセスできない」場合には、適当に時間をおいてリトライさせて、書き込み側の
処理が終わってから読み出すようにしていました。

ついでに、対象ファイルがtext形式(csv)だったのでヘッダ行とトレーラ行を追加して
おいて、監視側ではファイル読み込み後にチェックするようにしていました。
(ヘッダ行とトレーラ行にチェック用の行数等の情報を入れておいて、全行そろって
いるかチェックする)

ご参考まで。
eno
常連さん
会議室デビュー日: 2008/08/22
投稿数: 28
お住まい・勤務地: 代々木上原
投稿日時: 2008-09-03 16:10
同じプロセス内なら lock を使えば簡単なのですが、違うプロセス間で排他処理をどのようにするのかで悩んでいます。ためしに何もせずに実行してみたら、やはり「他のプロセスで使われているのでアクセスできない」という例外が発生しました。

File, FileInfo, FileStream クラスなど調べてみたのですが、現在他のプロセスで使われているかを調べる方法が分かりませんでした。
>>

後から、ファイルにアクセスするプロセスのほうで例外処理を書いておいて、例外が「正常」に発生してハンドリングされているのだから、これは正常ですよw調べる方法がわかりませんでしたって、、結局はランタイムエラーとしてしか想定できないんだから、実際にアクセスしてみてはじかれてみて、そこから処理を分岐させればいいだけかと思いますよ。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-09-03 18:14
読み込みプロセスが読み込んでいる最中に、次の書き込みタイミングが発生したら、どうしますか?
eno
常連さん
会議室デビュー日: 2008/08/22
投稿数: 28
お住まい・勤務地: 代々木上原
投稿日時: 2008-09-03 19:45
読み込みプロセスが読み込んでいる最中に、次の書き込みタイミングが発生したら、どうしますか?>>

どうもしないです。
早いもん勝ちです。
そして、占有します。
そして、鍵をかけます。

特別な相手からじゃないと、鍵もあけないし、メモリ上からいなくもなりません。

排他制御の設計上では、そういう事態を想定して特にネットDB上ではそうなっています。

基本的にはリソースの共有は不可能な仕様が殆どだと思います。
共有しているにしても、見かけ上が殆どですよね。同時には無理です。
理由は、実装上の問題ではなく、設計上。
プロセス間でメッセージのやりとりをするサービスがWindowsにはカーネルレベルでありますが、あくまで排他制御にとどまっていると思います。
排他制御はあくまでプロセス間メッセージの優先順位に基づいて、プロセスに対する処理(維持するか、破棄するか)が決定され、読み込みと書き込みが同時におこることはありません。ロック状態で発信元がプロセス間メッセージを管理するプロセスからでない限りは、解除されずアクセス自体が拒否されます。リネーム、書き込み、削除などファイルを開いているとできないそれです。同一スレッドからのメモリ開放処理でもOKで。。


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