Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 如何判断捕获的IOException是否是由另一个进程使用的文件引起的,而无需解析异常';s消息属性_.net_File_Ioexception_Robustness - Fatal编程技术网

.net 如何判断捕获的IOException是否是由另一个进程使用的文件引起的,而无需解析异常';s消息属性

.net 如何判断捕获的IOException是否是由另一个进程使用的文件引起的,而无需解析异常';s消息属性,.net,file,ioexception,robustness,.net,File,Ioexception,Robustness,当我打开一个文件时,我想知道它是否正被另一个进程使用,以便我可以执行特殊处理;任何其他例外我都会冒出来。IOException的Message属性包含“进程无法访问文件'foo',因为它正被另一个进程使用。”,但这不适用于编程检测。检测另一进程正在使用的文件的最安全、最可靠的方法是什么?当Win32本机函数返回的错误代码是错误共享\u冲突时,会引发此特定版本的IOException(.它的数值为0x20,但在异常的HRESULT属性上实际存储为0x80070020(它是调用MakeHRFromE

当我打开一个文件时,我想知道它是否正被另一个进程使用,以便我可以执行特殊处理;任何其他例外我都会冒出来。IOException的Message属性包含“进程无法访问文件'foo',因为它正被另一个进程使用。”,但这不适用于编程检测。检测另一进程正在使用的文件的最安全、最可靠的方法是什么?

当Win32本机函数返回的错误代码是
错误共享\u冲突时,会引发此特定版本的
IOException
(.它的数值为
0x20
,但在异常的
HRESULT
属性上实际存储为
0x80070020
(它是调用MakeHRFromErrorCode的结果)

因此,检查共享冲突的编程方法是检查
IOException
上的
HResult
属性中的值
0x80070020

public static bool IsSharingViolation(this IOException ex) {
  return 0x80070020 == Marshal.GetHRForException(ex);
}
但是,我确实怀疑,在由于共享冲突而引发异常的情况下,您到底想做什么。在引发异常的那一刻,另一个进程可能会退出,从而删除该冲突。

我没有足够的“代表”来评论,所以希望这个“答案”可以

被接受的答案正是我所寻找的,并且工作得非常完美,但是这里的人和类似问题的人都质疑检查文件是否被锁定的实用程序。测试文件是否被锁定的实用程序功能没有多大用处是正确的,因为在下一条语句中,状态可能已经改变

但是,尝试锁定操作,然后对锁定错误和常规错误做出不同的响应的模式是有效和有用的。最明显的做法是等待一点,然后重试该操作。这可以概括为以下帮助函数:

protected static void RetryLock(Action work) {
    // Retry LOCK_MAX_RETRIES times if file is locked by another process
    for (int i = 1; i <= LOCK_MAX_RETRIES; i++) {
        try {
            work();
            return;
        } catch (IOException ex) {
            if (i == LOCK_MAX_RETRIES || (uint) ex.HResult != 0x80070020) {
                throw;
            } else {
                // Min should be long enough to generally allow other process to finish
                // while max should be short enough such that RETRIES * MAX isn't intolerable
                Misc.SleepRandom(LOCK_MIN_SLEEP_MS, LOCK_MAX_SLEEP_MS);
            }
        }
    }
} // RetryLock
public string DoSomething() {
    string strReturn = null;
    string strPath = @"C:\Some\File\Path.txt";
    // Do some initial work...

    //----------------------------------------------------------------------------------------------------
    // NESTED FUNCTION to do main logic, RetryLock will retry up to N times on lock failures
    Action doWork = delegate {
        using (FileStream objFile = File.Open(strPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) {
            // Does work here if lock succeeded, else File.Open will throw ex
            strReturn = new StreamReader(objFile).ReadLine();
        }
    }; // delegate doWork
    //----------------------------------------------------------------------------------------------------

    RetryLock(doWork); // Throws original ex if non-locking related or tried max times
    return strReturn;
}

…无论如何,如果有类似需求的人发现该模式有用,请发布。

该类型真的是IOException还是从IOException派生的类型之一?出于兴趣,您为什么需要通过编程方式检测该类型?一旦发现另一个进程正在使用您的文件,您计划做什么?@Mark Byers,请参阅我的对接受的答案发表评论。为什么不直接使用
ex.HResult
而不是
Marshal.GetHRForException
?@Anders,因为HResult属性的可访问性级别为protected,所以通常不可访问。非常好的答案JaredPar,谢谢……在回答您的问题时;我需要检测此场景,因为我需要一个友好的消息表示层-它的确定,如果冲突可能不存在的那一刻后,由于我的应用程序的性质…谢谢again@richb:在.NET 4.5中,not 4.0I获得“与整型常量的比较无效;常量超出int类型的范围”,并且表达式的计算结果为False。这有效:(uint)Marshal.GetHRForException(w)=0x80070020如果您使用的是C#6,那么当(icatch(IOException ex ex ex)是最理想的情况
现在,异常只在我们要重试的循环中被捕获,如果我们不打算重试,它甚至不会在catch块中停止。