ファイルパスのセットが既存のファイルを表しているかどうかを確認する必要があります。
パスに現在のネットワーク上にないマシン上のネットワーク共有が含まれている場合を除いて、正常に機能します。この場合、タイムアウトするまでにかなり長い時間(30秒または60秒)かかります。
質問
存在しないネットワーク共有のタイムアウトを短縮する方法はありますか? (存在する場合はすぐに応答するので、1秒のタイムアウトで十分です)
キャッシュを開始してアルゴリズムをより複雑にすることなく、この問題を解決する他の方法はありますか? (つまり、これらのXネットワーク共有が存在しないことはすでにわかっています。残りの一致するパスをスキップしてください)
更新:スレッドの使用は機能しますが、特にエレガントではありませんが
public bool pathExists(string path)
{
bool exists = true;
Thread t = new Thread
(
new ThreadStart(delegate ()
{
exists = System.IO.File.Exists(path);
})
);
t.Start();
bool completed = t.Join(500); //half a sec of timeout
if (!completed) { exists = false; t.Abort(); }
return exists;
}
このソリューションは、試行ごとにスレッドの必要性を回避します。最初に、到達可能なドライブを確認し、それをどこかに保存します。
まず、IsDriveReady関数で設定できる「タイムアウト」値があります。私はそれを5秒間設定しましたが、あなたにとってうまくいくものなら何でも設定します。
以下の3つの方法が使用されます。
- 1つ目は、ドライブのUNC(\ servername\share)を取得するWNetGetConnectionAPI関数です。
- 2番目はメインメソッドです:Button1_Clickイベント
- 3つ目は、サーバーにpingを実行するIsDriveReady関数です。
これは私にとってうまくいきました!どうぞ:
'This API Function will be used to get the UNC of the drive Private Declare Function WNetGetConnection Lib "mpr.dll" Alias _ "WNetGetConnectionA" _ (ByVal lpszLocalName As String, _ ByVal lpszRemoteName As String, _ ByRef cbRemoteName As Int32) As Int32 'This is just a button click event - add code to your appropriate event Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim bIsReady As Boolean = False For Each dri As IO.DriveInfo In IO.DriveInfo.GetDrives() 'If the drive is a Network drive only, then ping it to see if it's ready. If dri.DriveType = IO.DriveType.Network Then 'Get the UNC (\\servername\share) for the ' drive letter returned by dri.Name Dim UNC As String = Space(100) WNetGetConnection(dri.Name.Substring(0, 2), UNC, 100) 'Presuming the drive is mapped \\servername\share ' Parse the servername out of the UNC Dim server As String = _ UNC.Trim().Substring(2, UNC.Trim().IndexOf("\", 2) - 2) 'Ping the server to see if it is available bIsReady = IsDriveReady(server) Else bIsReady = dri.IsReady End If 'Only process drives that are ready If bIsReady = True Then 'Process your drive... MsgBox(dri.Name & " is ready: " & bIsReady) End If Next MsgBox("All drives processed") End Sub Private Function IsDriveReady(ByVal serverName As String) As Boolean Dim bReturnStatus As Boolean = False '*** SET YOUR TIMEOUT HERE *** Dim timeout As Integer = 5 '5 seconds Dim pingSender As New System.Net.NetworkInformation.Ping() Dim options As New System.Net.NetworkInformation.PingOptions() options.DontFragment = True 'Enter a valid ip address Dim ipAddressOrHostName As String = serverName Dim data As String = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" Dim buffer As Byte() = System.Text.Encoding.ASCII.GetBytes(data) Dim reply As System.Net.NetworkInformation.PingReply = _ pingSender.Send(ipAddressOrHostName, timeout, buffer, options) If reply.Status = Net.NetworkInformation.IPStatus.Success Then bReturnStatus = True End If Return bReturnStatus End Function
スレッドを使用してチェックを行います。スレッドがタイムアウトする可能性があると思います。
UNC
名に解決してみてください。ping
してみてください。Googleがリファラーでない場合、EEは無料で回答を表示しません。 EEへのリンクは役に立ちません。
OPは、私が最初の回答で言及した記事を見つけ、彼の質問に ソリューションのソースコード を含めるのに十分親切でした。
別の「スレッドソリューション」:
/// <sumary>Check if file exists with timeout</sumary>
/// <param name="fileInfo">source</param>
/// <param name="millisecondsTimeout">The number of milliseconds to wait,
/// or <see cref="System.Threading.Timeout.Infinite"/> (-1) to wait indefinitely.</param>
/// <returns>Gets a value indicating whether a file exists.</returns>
public static bool Exists(this FileInfo fileInfo, int millisecondsTimeout)
{
var task = new Task<bool>(() => fileInfo.Exists);
task.Start();
return task.Wait(millisecondsTimeout) && task.Result;
}
出典: http://www.jonathanantoine.com/2011/08/18/faster-file-exists/
「ドライブが十分に速く応答しない」という懸念があるので、これは速度と「真実」の間の妥協点です。 100%確実にしたい場合は使用しないでください。
これは私にとって素晴らしい働きをしました!
C#のIsDriveReady()は次のとおりです。
using System.Net;
private bool IsDriveReady(string serverName)
{
// *** SET YOUR TIMEOUT HERE ***
int timeout = 5; // 5 seconds
System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingOptions options = new System.Net.NetworkInformation.PingOptions();
options.DontFragment = true;
// Enter a valid ip address
string ipAddressOrHostName = serverName;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = System.Text.Encoding.ASCII.GetBytes(data);
System.Net.NetworkInformation.PingReply reply = pingSender.Send(ipAddressOrHostName, timeout, buffer, options);
return (reply.Status == System.Net.NetworkInformation.IPStatus.Success);
}
スレッドタイムアウト関数を使用したpathExistsは便利でしたが、正しく機能するにはFile.ExistsからDirectory.Existsに変更する必要があることにようやく気付きました。