のにっき

【C#】ネットワーク共有フォルダへの接続待ち対策

会社でツールを作っていると結構起こる問題だと思ったのですが、
意外とネットに乗ってなかったので自己解決した内容をまとめます。

ネットワークフォルダにアクセスできなかったらどうなる?

C#で指定のフォルダにアクセスする際に、必ずフォルダ存在判定を行うと思います。 System.IO.Directory.Exists()
この関数を使うのが一般的だと思いますが、Exists関数に限らず(System.IO)クラスの
メソッドでフォルダにアクセスすると、厄介な挙動をします。

Exists関数で様々な条件のフォルダを判定した時の挙動

A)ローカルフォルダ
→ 存在する=true、存在しない=false を返す
B)ネットワークフォルダ ※アクセス可の状況
→ 存在する=true、存在しない=false を返す
C)ネットワークフォルダ ※アクセス不可の状況
20秒以上接続待機(停止)し、エラーを返す
厄介な挙動はもちろんC)の状況ですね。
これではアクセス待機のせいで処理が以上に遅くなってしまいます。
今回は、この接続待ちの時間を短縮させて
ネットワークフォルダのアクセス可否判定を行う方法をご紹介します。

並列処理で時間を計って勝手にタイムアウト判定を行う

接続待ちの時間を短縮させる方法は調べても見つかりませんでした!
ですので、並列処理を使って
自分で指定の時間が過ぎたら処理を中止させる関数を作りました。

/// <summary>
/// フォルダ存在判定【タイムアウト付き】
/// </summary>
/// <param name="path">検索されるフォルダパス</param>
/// <returns>検索結果( True = 存在する )</returns>
public static bool IsFolderSonzai_Out(string path)
{
    int i_Wait = 150;   // この値【ms】だけ処理待ち
    bool exists = true;
    Thread t = new Thread
    (
        new ThreadStart(delegate ()
        {
            exists = Directory.Exists(path);
        })
    );
    t.Start();
    bool completed = t.Join(i_Wait);
    if (!completed)
    {
        exists = false;
        t.Abort();
    }
    return exists;
}

上記関数がタイムアウト付きのフォルダ存在判定処理です。
1.別スレッド(t)でフォルダ存在判定を行う
2.指定時間(i_Wait )の時間だけスレッドの完了待ちを行う
3.指定時間経過後(もしくは処理終了後)、スレッド(t)が終了していなかったら
  スレッドを強制終了。アクセス不可と判定して「false」を返す

こんな感じの処理を行う関数になってます。

以上です。 並列処理は高速化でよく使われますが、今回のように
処理待ちのタイムアウト判定で使う事もできるので、より深く理解すると
組み込みの幅が広がる感覚があって楽しくなります。