tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルTry Catch で Resumeのような動作
記事No11542
投稿日: 2015/12/10(Thu) 17:39
投稿者OrientalMelody
いつもお世話になっております。

Windows7(32bit)上でVB2010により開発をしております。

ファイルオープン時にファイルが使用中だったときに、
ユーザにファイルクローズを促して、ファイルオープンを
再試行させるルーチンを作成しようしています。

VB.NETですが、以前、On Errorルーチンで、
ファイル使用中のときは、エラーハンドラに飛ばして
Err.Number = 57 のときに、
ユーザにファイルクローズを促すメッセージを出して、
Resume で再度、開きに行くようにしたのですが、
これをTry Catchステートメントで実現させようとした場合は、
やはりファイル毎にTry CatchをDo Loopで括る必要があるのでしょうか?

以下にOn Error文とTry Catch文のソースコードを記述します。

Form1に Button1 と Button2 を貼り付けてから、
Form1のコードを開き、以下のコードを貼り付ける。

Option Explicit On
Imports System.IO
Public Class Form1

    'On Error使用時
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        On Error GoTo Errhandler
        Dim sFile As String = ""
        sFile = "D:\AAA.csv"
        Using str_Writer As New StreamWriter(sFile, True, System.Text.Encoding.GetEncoding("Shift_JIS"))
            str_Writer.WriteLine("1,xxx")
        End Using
        sFile = "D:\BBB.csv"
        Using str_Writer As New StreamWriter(sFile, True, System.Text.Encoding.GetEncoding("Shift_JIS"))
            str_Writer.WriteLine("1,yyy")
        End Using

        Exit Sub
Errhandler:
        If Err.Number = 57 Then
            'ファイル使用中
            Dim sFileOnly As String
            If MsgBox(sFile & " は既に開かれています。!" & vbCrLf & vbCrLf & _
                    sFile & " を閉じてから再試行ボタンをクリックしてください。", _
                      MsgBoxStyle.RetryCancel) = MsgBoxResult.Retry Then
                Err.Clear()
                Resume '←ここでリトライする。
            End If

        Else
            'その他のファイルエラー
            MsgBox(sFile & "アクセス中にエラーが発生しました!" & vbCrLf & vbCrLf & _
                     Err.Number & " " & Err.Description, MsgBoxStyle.OkOnly)
        End If
    End Sub

    'Try Catch使用時
    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        Dim sFile As String = ""
        Do
            Try
                sFile = "D:\AAA.csv"
                Using str_Writer As New StreamWriter(sFile, True, System.Text.Encoding.GetEncoding("Shift_JIS"))
                    str_Writer.WriteLine("1,xxx")
                End Using
                Exit Do
            Catch ex As System.IO.IOException
                'ファイル使用中
                If MsgBox(sFile & " は既に開かれています。!" & vbCrLf & vbCrLf & _
                        sFile & " を閉じてから再試行ボタンをクリックしてください。", _
                        MsgBoxStyle.RetryCancel) = MsgBoxResult.Retry Then
                Else
                    Exit Sub
                End If
            Catch ex As Exception
                'その他のファイルエラー
                MsgBox(sFile & "アクセス中にエラーが発生しました!" & vbCrLf & vbCrLf & _
                         ex.GetType.ToString & " " & ex.Message, MsgBoxStyle.OkOnly)
                Exit Sub
            End Try
        Loop

        Do
            Try
                sFile = "D:\BBB.csv"
                Using str_Writer As New StreamWriter(sFile, True, System.Text.Encoding.GetEncoding("Shift_JIS"))
                    str_Writer.WriteLine("1,yyy")
                End Using
                Exit Do
            Catch ex As System.IO.IOException
                'ファイル使用中
                If MsgBox(sFile & " は既に開かれています。!" & vbCrLf & vbCrLf & _
                        sFile & " を閉じてから再試行ボタンをクリックしてください。", _
                        MsgBoxStyle.RetryCancel) = MsgBoxResult.Retry Then
                Else
                    Exit Sub
                End If
            Catch ex As Exception
                'その他のファイルエラー
                MsgBox(sFile & "アクセス中にエラーが発生しました!" & vbCrLf & vbCrLf & _
                         ex.GetType.ToString & " " & ex.Message, MsgBoxStyle.OkOnly)
                Exit Sub
            End Try
        Loop
    End Sub
End Class

このように複数のファイルの処理の場合は、それぞれのファイルをDo Loopで括るので
Try Catchの方がソースコードが長くなってしまいます。

Try Catchでは Resume 機能が無いようですが、On Errorルーチン並みにソースコードを短く書く方法は
あるのでしょうか?

宜しくお願いいたします。

[ツリー表示へ]
タイトルRe: Try Catch で Resumeのような動作
記事No11543
投稿日: 2015/12/10(Thu) 20:13
投稿者魔界の仮面弁士
> やはりファイル毎にTry CatchをDo Loopで括る必要があるのでしょうか?

2 つのファイルのために、2 つの Try Catch が書かれていますが、
処理として違うのがファイル名だけなのであれば、
ファイル名をコレクションなり配列にして処理すれば、
Catch 句は 1 つで済むと思います。


ファイル名だけでなく、それぞれの処理も異なるなら、
それらの処理を匿名メソッド/デリゲートにするのも手です。

以下、C# のサンプルですが、VB でも同様に処理できるかと。
http://blog.xin9le.net/entry/2013/09/08/173009

[ツリー表示へ]