系统.IO.IOException: 进程无法访问文件 '文件名'。

3
我有一个Windows服务中的方法如下:

我在我的Windows服务中有一个以下方法:

System.IO.File.Copy(path, ConfigurationManager.AppSettings["BulkInsertGiftRegisterCreatorDirectory"] + System.IO.Path.GetFileName(path));

Loyalty.Entity.Base.FileInfo file = new Loyalty.Entity.Base.FileInfo();
file.FileName = path;
request.Object = file;

ResponseBase response = new ResponseBase(request);
RequestConnection connection = new RequestConnection("cn");
FileManager fileManager = new FileManager(request, connection);
response = fileManager.OfflineGiftRegisterBulkInsert();

System.IO.File.Delete(ConfigurationManager.AppSettings["BulkInsertGiftRegisterCreatorDirectory"] + System.IO.Path.GetFileName(path));

// here is the part of stored procedure that uses file
SELECT @SCRIPT= 'BULK INSERT GIFT_CARD.GIFT_TEMP'
                            +' FROM '''
                            + @FILE_PATH
                            +''' WITH ('
                                 +'FIELDTERMINATOR = '','','
                                 + 'KEEPNULLS'
                            +');'

我可以手动从文件系统删除文件,但是这段代码会提示错误“哎呀!System.IO.IOException:另一个进程正在使用文件 'filename',因此无法访问。”

我在stackoverflow和其他地方搜索了类似的问题,但没有找到任何有用的信息。Copy或Delete方法返回void,并且我的代码中没有流可供处理。

该怎么解决呢?

提前致谢。


2
“do something else” 部分是在做什么?我猜它正在对被复制/删除的文件进行某些操作。而且我有一种感觉,这个操作在这里非常重要。 - Dirk Vollmar
我调用一个存储过程,该存储过程使用文件路径来批量插入文件中包含的行。 - xkcd
@anilca:这意味着文件已经被打开(可能是由执行存储过程的方法或存储过程本身打开的)。确保它被正确关闭。如果您展示您的代码,我们可以帮助您找到问题所在。 - Dirk Vollmar
@ChrisNel52 我正在使用与 Windows 服务相同的用户登录。 - xkcd
那么,我的回答有帮助吗? - Vercas
显示剩余5条评论
3个回答

5

这里给你介绍一种检查文件是否正在使用的方法:

public static System.Boolean FileInUse(System.String file)
{
    try
    {
        if (!System.IO.File.Exists(file)) // The path might also be invalid.
        {
            return false;
        }

        using (System.IO.FileStream stream = new System.IO.FileStream(file, System.IO.FileMode.Open))
        {
            return false;
        }
    }
    catch
    {
        return true;
    }
}

此外,为等待我制作的文件:
public static void WaitForFile(System.String file)
{
    // While the file is in use...
    while (FileInUse(file)) ; // Do nothing.
}

我希望这可以帮助你!

这不是 Windows 应用程序,@Vercas。这是一个 Windows 服务。 - xkcd
@anilca 那请原谅我。我从未使用过Windows服务,所以我会让它什么都不做。 - Vercas

4
在浏览代码之前,您可能需要使用process explorer来识别有哪些进程正在处理句柄。这可能排除您没有考虑到的一些问题。
更新
由于您正在使用定时器,您必须确保您的方法是可重入的,并且您没有任何竞争条件...例如,定时器的滴答声比您处理事件的速度更快。
请参阅此问题此答案

1
更好的解决方案是,在使用Vercas所示的FileInUse函数之前添加以下两行代码:
GC.Collect();
GC.WaitForPendingFinalizers();

请解释为什么这是更好的解决方案。另外,一般来说,答案应该能够独立存在。现在,这看起来更像是一条评论或回复,而不是一个答案。 - p.s.w.g
我认为这是更好的解决方案,因为我测试过了。我遇到了同样的问题,File.Copy后跟一个File.Delete会导致错误。首先我只测试了"FileInUse",它可以工作。但系统需要大约10到15秒才能删除文件。然后我使用了我在这里分享的代码行,在某些情况下可以工作,在其他情况下则不能。因此,我结合了两种解决方案:首先调用我在这里分享的两行代码,然后使用函数“FileInUse”测试文件,最后调用“File.Delete”。它运行得非常顺畅,文件几乎立即被删除。 - user2501815

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接