DOBON.NET DOBON.NETプログラミング掲示板過去ログ

usingでの例外発生

環境/言語:[XP VS2008 C#]
分類:[.NET]

はじめまして。
いつも参考にさせていただいてます。

usingを使用してFileStreamを使おうといているのですが、
例外がおこってプログラムが止まってしまいます。

---
string FileName = @"C:\test.txt";
using (FileStream fs = new FileStream(FileName,FileMode.Open,FileAccess.ReadWrite,FileShare.None))
{
処理1
}
処理2
---

上のようなコードを書いているのですが、
"test.txt"が他のプログラムによってロックされている時、
FileStreamのインスタンス作成時に「IOException」の例外が起こり、
エラーダイアログが出てプログラムが止まってしまいます。

やりたい事はインスタンス作成および「処理1」内で例外がおこった場合は
処理を中断して「処理2」に処理を持っていきたいのですが、
使い方を間違っているのでしょうか?
それとも他の原因があるのでしょうか?


---
string FileName = @"C:\test.txt";
FileStream fs = null;
try
{
FileStream fs = new FileStream(FileName,FileMode.Open,FileAccess.ReadWrite,FileShare.None);
処理1
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if(fs!=null)
fs.close();
}
処理2
---
このようにtry〜catch〜finallyを使えば、実現出来るので、
とりあえずは回避はできているのですが。

文書がヘタでスイマセンが、ご教授宜しくお願いいたします。
  • 題名: Re[1]: usingでの例外発生
  • 著者: Hongliang
  • 日時: 2009/11/18 19:03:57
  • ID: 25855
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
catch を行う場合は、using を使わない(finally 節で自分で Dispose する)か
try {
  using (...) {
  }
}
catch (...Exception ex) {
  ...
}
と書くかのどちらかですね。
■No25854に返信(レインさんの記事)
> usingを使用してFileStreamを使おうといているのですが、
> 例外がおこってプログラムが止まってしまいます。

> このようにtry〜catch〜finallyを使えば、実現出来るので、
> とりあえずは回避はできているのですが。

  無いこともありませんが・・・

  http://d.hatena.ne.jp/NyaRuRu/20070426/p1

  http://www.atmarkit.co.jp/fwin2k/win2ktips/306openfiles/openfiles.html

  簡単に・・・と言うのであれば、Try〜Catchが正解と思いますが。

以上。
Hongliang様、オショウ様
返信ありがとうございます。

usingの用途が分からなくなってきました。。。

今回やりたいことは、
1、ファイルをオープンする。
2、ファイルがオープンできたら「処理1」を実行。
  エラーが起こればプログラムを止めることなく「処理2」の処理に移る。
と、いう事です。

usingを使用している時に例外が起こるとエラーダイアログが出るのが正規の動作ということでイイのでしょうか?
■No25859に返信(レインさんの記事)

> usingを使用している時に例外が起こるとエラーダイアログが出るのが正規の動作ということでイイのでしょうか?

  using は、オブジェクトの管理に関わる機能を取りまとめて
  くれるだけ、その中身の機能の動作には関わりません。

  今回問題なのは、ロックされているファイルを書き変えたい
  モードでオープンした場合、エラーすると言うだけで、using
  とは直接的には関わりません。

  たまたまusingの行内の処理で、開くと言う動作を行っている
  為、開けないのでエラーが発生している。

  usingを使わなくても、実際のオープン処理が実行される段階
  で、エラーするので、Try〜Catchは必要・・・

  『Try〜Catchを使わない』『エラーさせない』
  と言うことを実現する為には、私が提示したURLの内容に
  従って、オープンできるか?と言うことを検証した結果から
  オープン=>書き換え を行なう処理へ行くか、止めるか。
  と言う動作になるだけ。

  しかしながら、Try〜Catchを使わない方が、はるかに多くの
  コードの処理(コスト)がかかるように思われますが・・・
  それでもそうしたいのであれば、そういう機能をインプリす
  れば、満足がいく結果を得られるでしょう。

※ なんでTry〜Catchじゃ〜ダメなの?
  昨日からこの件にこんだけ時間を浪費して、それでも得るも
  のがあるなら、それでもよいですが・・・
  あまりに無駄のような・・・

以上。
2009/11/19(Thu) 10:38:57 編集(投稿者)

# Try〜Catch ではなく、try〜catch ですよ。>オショウさん


■No25859に返信(レインさんの記事)
> usingの用途が分からなくなってきました。。。
using ブロックは、IDisposable なオブジェクトを、
たとえ例外が発生しようと発生しなかろうと、確実に
最後に Dispose メソッドが呼ばれるようにするためのものです。


> usingを使用している時に例外が起こるとエラーダイアログが出るのが正規の動作ということでイイのでしょうか?
例外処理を行いたいのであれば、try ブロックを使って処理してください。

例外のメッセージを、別のメッセージやログ出力に置き換えるのか、
例外をそのまま未処理のままにしておくのか、例外を握り潰すのかは、
using の動作そのものとは関係ありません。


> 1、ファイルをオープンする。
> 2、ファイルがオープンできたら「処理1」を実行。
>   エラーが起こればプログラムを止めることなく「処理2」の処理に移る。
> と、いう事です。

こういう感じで如何でしょう。

案1)
 try {
  ファイル操作(fs.Close() が必要)
  処理1
 } finally {
  処理2
 }

案2)
 try {
  ファイル操作(fs.Close() が必要)
 }catch(…){
  エラー回復処理
 }
 処理2
■No25861に返信(オショウさんの記事)

using は例外に関して関知しないということで理解すればイイのですね?

> ※ なんでTry〜Catchじゃ〜ダメなの?
>   昨日からこの件にこんだけ時間を浪費して、それでも得るも
>   のがあるなら、それでもよいですが・・・
>   あまりに無駄のような・・・

http://msdn.microsoft.com/ja-jp/library/system.io.filestream%28VS.80%29.aspx

を参照してプログラムを作成していまして、
usingを使用すればブロック内で例外が起こればそのまま握り潰してくれるものだと思い込んでいました。
この使用例でも(まだ試せてないので今から試してみます)例外が起こるとエラーで止まってしまう事になるんですよね?

例外を処理出来ないとなると、どういった場面で using を使用すれば良いのかが分からなくなったのです。

今後の事もあるので、今のうちに理解しておこうと思いまして書き込みさせていただきました。
  • 題名: Re[4]: usingでの例外発生
  • 著者: レイン
  • 日時: 2009/11/19 12:20:41
  • ID: 25866
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
■No25862に返信(魔界の仮面弁士さんの記事)

>>usingを使用している時に例外が起こるとエラーダイアログが出るのが正規の動作ということでイイのでしょうか?
> 例外処理を行いたいのであれば、try ブロックを使って処理してください。

初心者なのでイロイロと検索していた時に using を使っているサンプルが
多かったので、それに倣ってプログラムを作成してました。

例外が起こりえる場合は using は使用せず、try〜catch を使用するという事でよろしいでしょうか?


現在、
--
try
{
 ファイルオープン
 処理1
}
catch
{
}
finally
{
 ファイルクローズ
}
処理2
--

で希望する動きをしてくれています。
この処理は

--
try
{
 ファイルオープン
 処理1
}
finally
{
 ファイルクローズ
}
処理2
--

と、同等だと思い込んでいたので using を使用しようとした次第です。
実際は別物だという事で理解すれば良いのですか?
■No25864に返信(レインさんの記事)
> usingを使用すればブロック内で例外が起こればそのまま握り潰してくれるものだと思い込んでいました。

using は、finally 句の生成を助けるだけであって、
catch 句の生成は行いません。
例外は握りつぶされたりはせず、そのまま例外として処理されます。
http://www.divakk.co.jp/aoyagi/csharp_tips_using.html


> と、同等だと思い込んでいたので using を使用しようとした次第です。
やってみると分かるかと思いますが、例外発生時には異なる動作となります。
例外が握りつぶされるのは前者だけです。

using の展開結果は、その 2 例どちらとも微妙に異なりますが、
catch 句が生成されるわけではないという点で見れば、後者の例が近いですね。
■No25868に返信(魔界の仮面弁士さんの記事)

> 例外は握りつぶされたりはせず、そのまま例外として処理されます。

ようやく理解できた気がします。
ありがとうございます。

あと一点モヤモヤしたものがあります。

> http://www.divakk.co.jp/aoyagi/csharp_tips_using.html

の中で FileStream のインスタンスを作成していますが、
この時に例外が起こるとプログラムが止まってしまうと思うのですが、
これは意図的にそのように作ってあると理解して良いものなのでしょうか?

そういう意図で作りたくない場合は using は不適だという事になります。
「FileStream インスタンスの作成時に例外が起きない!」
という確信があれば使用出来ると思うのですが、その確信は持てないので。。。

となると、どういった時に using 使用すれば良いものなのでしょうか?



ちょうど Dispose について調べていました。

> > あと一点モヤモヤしたものがあります。
>
>>http://www.divakk.co.jp/aoyagi/csharp_tips_using.html
>
> の中で FileStream のインスタンスを作成していますが、
> この時に例外が起こるとプログラムが止まってしまうと思うのですが、
> これは意図的にそのように作ってあると理解して良いものなのでしょうか?

ん?以下の個所ですか?

---------------------------------------------------------------
逆に言うとusingは自動的にtry ... finally を作ってくれて、finallyで必ずDispose()を呼び出すようにしてくれるだけです。なので、例外に対処するために下記のようなコードになることが多いでしょう。

public void Func() {
using (FileStream fs = new FileStream("test.txt", FileMode.Read)) {
using (StreamReader sr = new StreamReader(fs)) {
try {
// 処理する
}
catch () {
// 例外処理
}
}
}
}
---------------------------------------------------------------

このサンプルは、あくまで FileStream のインスタンスを安全に解放するためのサンプルであって
インスタンス生成時のエラーまで考慮してない例だと思いますよ。
ファイル生成時のエラーについては、以下の対処でいいと思います。
FileStream 生成時のエラーは、FileStream のインスタンスを using する前の問題なので
さらに一皮 try 〜 catch をかぶせておけば問題ないです。

public void Func() {
    FileStream fs;
    try
    {
        using (fs = new FileStream("test.txt", FileMode.Read))
        using (StreamReader sr = new StreamReader(fs))
        {
            try
            {
                // 処理する
            }
            catch (Exception ex)
            {
                // 例外処理
            }
        }
    }
    catch (Exception)
    {
        // FileStream の生成に失敗した場合の例外処理;
    }
}

using はあくまで「安全にリソースを解放するための装置」と考えておけばいいかと。
  • 題名: Re[9]: usingでの例外発生
  • 著者: レイン
  • 日時: 2009/11/20 9:21:12
  • ID: 25880
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
■No25871に返信(ひらぽんさんの記事)

ようやくスッキリしました。

サンプルを探している時に using ブロック内で try〜catch しているのは見かけていたので、例外処理を考えているものとして、
インスタンス作成時も例外処理してくれるものだと、思い込んでしまっていました。


> ファイル生成時のエラーについては、以下の対処でいいと思います。
> FileStream 生成時のエラーは、FileStream のインスタンスを using する前の問題なので
> さらに一皮 try 〜 catch をかぶせておけば問題ないです。

このソースだと納得することが出来ました。

こういう初歩的な事に対して、コメント頂いた方々ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板