c# 在后台线程中出现未经授权的错误

Posted

技术标签:

【中文标题】c# 在后台线程中出现未经授权的错误【英文标题】:Unauthorized error in c# while on background thread 【发布时间】:2017-09-02 18:56:09 【问题描述】:

我创建了一个 ASP.NET Web 应用程序,其中需要删除一个文件。下面是完美执行这个操作的代码

File.Delete(path);

但是,当我尝试在这样的后台线程上执行此操作时

Task.Run(() => File.Delete(path));

然后它会抛出拒绝访问此路径的异常。我尝试让 IIS_IUSRS 和 IUSR 完全访问该路径,但错误仍然存​​在。有人可以解释这里发生了什么。为什么文件被第一个代码删除,即在主线程上,而不是在后台线程上。 C# 中的背景线程是否以不同的身份运行?

【问题讨论】:

这里的关键字是线程池 Task.Run(() => File.Delete(path)); 之后,你对文件还有什么别的吗?您不是在等待任务完成。如果另一个线程开始访问该文件....... @PeterBons 不,在此之后,文件根本不使用。这就是我们决定删除它的原因。 等待Task.Run(() => File.Delete(path)); @hugorgor 我们不想等待这个电话。原因是我们不太关心这个任务的结果。但是,让我向您保证,无论我们是否使用 await,行为都是相同的。 【参考方案1】:

您提供的两种方法之间的主要区别在于File.Delete(path) 立即调用 WinAPI 函数DeleteFile,而Task.Run(() => File.Delete(path)) 执行相同操作但有一些延迟。

在这么短的时间内可能会发生一些事情。例如。 Windows 搜索服务可以打开文件进行索引,防病毒可以打开文件进行分析,或者其他一些进程可以对这个(我假设)新创建的文件做一些事情。

如果您确定您的应用程序稍后不会重新打开此文件并且在任何地方都没有保存文件句柄,我建议您使用多次尝试来避免此类问题:

Task.Run(() =>

    const int attemptsNum = 10;
    for (int attempt = 0; attempt < attemptsNum; attempt++)
    
        try
        
            File.Delete(path);
            break;
        
        catch
        
            if (attempt == attemptsNum - 1)
            
                throw; // or log exception here
            
            else
            
                await Task.Delay(500);
            
        
    
);

【讨论】:

这将对应用程序的性能产生不利影响。 你确定这种效果是有形的吗?我们正在谈论每个文件最大值的几毫秒。您希望每秒删除多少个文件? 每个用户对该操作方法的每个请求都有一个文件。让我告诉你为什么你被否决了。如果文件在第一次迭代中被删除,那么您将在剩余的 9 次迭代中获得异常,然后每次您将等待半秒。这样,您每次尝试删除文件时都会不必要地等待大约 4-4.5 秒。由于您的线程将用于此任务,因此线程池中可用的线程将越来越少,并且会影响可伸缩性。 同时使用异常控制应用程序流是非常糟糕的做法。 我显然只是忘了在File.Delete(path) 之后添加break。固定。

以上是关于c# 在后台线程中出现未经授权的错误的主要内容,如果未能解决你的问题,请参考以下文章

C# 调用 ListView 不起作用(后台线程)

C#如何在BackgroundWorker 后台线程中使用定时器?

关于C# WPF线程后台运行的

c#线程之前台线程后台线程及使用

C#前台线程与后台线程的区别和联系 (转)

C# BackgroundWorker 详解