Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.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
Visual studio C#.NET核心3.1代码在Visual Studio中运行时间长,但发布的单个文件可执行文件消耗了大量内存_Visual Studio_.net Core - Fatal编程技术网

Visual studio C#.NET核心3.1代码在Visual Studio中运行时间长,但发布的单个文件可执行文件消耗了大量内存

Visual studio C#.NET核心3.1代码在Visual Studio中运行时间长,但发布的单个文件可执行文件消耗了大量内存,visual-studio,.net-core,Visual Studio,.net Core,我想发布我的应用程序,因为它运行良好。但当我把它作为一个打包的应用程序运行时,它使用了高达20GB甚至更多的巨大内存。在VisualStudio2019中运行它,我无法重现该问题。它运行的时间也很长,在VS中,即使有很多文件,也只需几秒钟 到目前为止,我尝试了我认为几乎所有的方法,删除了所有的并行性,ConcurrentQueue-to-Queue等,但问题仍然存在 对于VS和可执行文件,您必须“以管理员身份运行”。看起来您试图并行处理驱动器上的所有文件,并且可能最终缓存内存中的每个文件,因为

我想发布我的应用程序,因为它运行良好。但当我把它作为一个打包的应用程序运行时,它使用了高达20GB甚至更多的巨大内存。在VisualStudio2019中运行它,我无法重现该问题。它运行的时间也很长,在VS中,即使有很多文件,也只需几秒钟

到目前为止,我尝试了我认为几乎所有的方法,删除了所有的并行性,ConcurrentQueue-to-Queue等,但问题仍然存在


对于VS和可执行文件,您必须“以管理员身份运行”。

看起来您试图并行处理驱动器上的所有文件,并且可能最终缓存内存中的每个文件,因为辅助方法最终会相互阻塞。在调试器下运行太慢,无法发生这种情况

NET已经提供了一些机制,用于在具有多个线程的步骤管道中处理单个消息,并限制一次可以在内存中存储多少项

很可能您只需要使用一个或多个类。这些类在其输入缓冲区中接受消息,并使用一个或多个辅助任务按顺序处理它们。它们还允许为输入缓冲区设置边界,以避免缓冲区溢出(如果工作进程太慢)

为了解决您的问题,您可能只需要一个DOP>1的ActionBlock和一个有限的输入缓冲区,例如:

var options=new new ExecutionDataflowBlockOptions
      {
         MaxDegreeOfParallelism = 5,
         BoundedCapacity=10
});
var block=new ActionBlock<string>(filePath=>{
  //Do something with that file
},options);

//Feed all files to the block

foreach(var file in Directory.EnumerateFiles("C:\\","*",SearchOptions.AllDirectories))
{
    await block.SendAsync(file);
}

block.Complete();
await block.Completion;
当前代码存在问题

代码过于复杂,以不适当甚至冲突的方式使用多个并发和并行结构。看起来它试图处理本地磁盘中的所有文件,但最终加载内存中的每个文件(或至少每个文件名或FileInfo对象),等待一些被阻止的方法来处理它们。最有可能的是,在VisualStudio中运行此操作太慢,无法显示此行为

  • 首先,BackgroundWorker已经过时,自2012年以来完全被用于进度报告的Task和Progress类所取代。那是8年。没有充分的理由再使用它了

  • 一个任务不是一个线程,它只是一个将在某个线程上运行的作业(任务)。它并不意味着要活很长时间,也绝对不意味着要充当一个带有循环的线程

  • PLINQ和
    Parallel
    类的方法旨在实现并行性,即使用所有可用内核对大量内存数据进行CPU密集型处理。它们不适用于并发性,即需要同时执行不同的操作,特别是不需要CPU的IO场景

  • 添加信号量只能通过让所有这些构造相互阻塞来实现


20GB的RAM几乎肯定是内存泄漏,可能是由于创建和垃圾收集了大量临时对象,或者忘记处理确实需要处理的对象造成的。也许这些对象仍然被应用程序引用,所以它们不能被GC调用?这与并行性或ConcurrentQueue无关etcI只是查看了代码。它需要严格简化,因为它使用过时的BackgroundWorker和任务,就像它是线程而不是任务一样,以及PLINQ和并发队列。对于初学者来说,BGW完全被
Task.Run
取代。如果要报告进度,请使用
进度
类。任务也不是线程,它们表示将在线程上运行的作业(任务),因此不应该永远运行。最后,
PLINQ
Parallel
用于并行处理大量数据,即使用所有可用的内核。它们并不意味着要同时处理内容如果你想处理大量文件,也许你所需要的只是使用一个并行度设置为>1的
ActionBlock
,并将文件以循环方式发送给它。ActionBlock已经有了一个输入队列,所以您不需要ConcurrentQueue或semaphoresEven,它们可以用缓存对象快速填充内存。也许这就是这里发生的情况-VS运行得太慢,您无法注意到,但在发布版本中,所有本地文件最终都会缓存在内存中,因为由于信号量、任务和PLINQ相互阻塞,工作方法处理它们的速度太慢。要解决此问题,请将块的
BoundedCapacity
设置为固定数字,而不是无限
var enumOptions=new EnumerationOptions { 
    IgnoreInaccessible=true, 
    RecurseSubdirectories=true
};

foreach(var file in Directory.EnumerateFiles("C:\\","*",options))
{
    await block.SendAsync(file);
}