使用C#

时间:2019-05-07 19:05:49

标签: c# multithreading asp.net-mvc-4 filesystems

我正在优化一个占用大量磁盘空间的应用程序,该应用程序会生成大量临时文件,但由于存储空间有限,我每天都必须清理文件夹。所以,我想知道什么是最好的方法。这些文件位于网络磁盘上,可通过IIS上的虚拟文件夹进行访问,因此它们看起来像是站点自己的文件夹的一部分。

我有一个在线PDF编辑器,使用Aspose.PDF for .Net。 在使用该应用程序时,它会生成许多临时文件,但仅在创建所有临时文件后才呈现视图。因此,我正在使用Parallel.For语句来进行临时文件创建,限于机器上可用处理器的数量。

最初是按顺序完成的,并且考虑到每页大约需要1到3秒的时间,具体取决于页面质量(Aspose限制,无法对其进行优化),它花费的时间太长。我已经设法使操作并行化,但是时间仍然太长。

另一方面,我有一个例程可以删除多个目录中所有早于24小时(86400秒)的文件。首先,这是根据每个用户请求(页面加载)完成的,因此它在页面生命周期中执行了几次,每次都只删除一堆文件。 所有IIS应用程序池每天都会在00小时进行回收,因此现在我要在Application_Start上进行此操作,但是我担心它会减慢第一个用户请求的速度,因为它必须删除约4.5万个文件(今天,该应用程序已删除已使用了7个小时,已经有3万个文件)。我想知道是否有更好的方法来执行以下操作:

-在Session_End删除一些旧文件(例如,删除4小时之前的文件)

-在Application_End(大于24小时)上删除其余的(如果有的话)。

此外,假设我不必等待它们完成,就可以通过使用异步任务来调用此例程。

对于删除,我在for循环上使用System.IO.FileInfo.Delete()。

临时文件创建过程

     Parallel.For(0, TotalPages, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, pageCount =>
                 {
                     using (MemoryStream imageStream = new MemoryStream())
                     {
                         var po = new PageObject();
                         var idx = pageCount + 1;
                         PngDevice p = new PngDevice(); // bajamos un poco la resolución
                         p.RenderingOptions.UseNewImagingEngine = true;
                         p.Process(doc.Pages[idx], imageStream);   //  esta instrucción demora cerca de 1 segundo
                                                                   //System.Drawing.Image image = System.Drawing.Image.FromStream(imageStream);
                                                                   //ScaleImage(image, 1138, 760, path_base + fileMask + "-" + idx + ".png", out height, out Aratio);
                                                                   //image.Dispose();
                         using (System.Drawing.Image image = System.Drawing.Image.FromStream(imageStream))
                         {
//this scales the image and writes it to a disc
                             ScaleImage(image, 1138, 760, path_base + fileMask + "-" + idx + ".png", out height, out Aratio);
                         }

                         if (idx == 1) { fields = CheckFields(doc, idx, "image" + fileMask + "-" + idx + ".png", fields, Convert.ToDouble(Aratio)); }
                         po.pageNumber = idx;
                         po.pageName = "image" + fileMask + "-" + idx + ".png";
                         po.Height = height;
                         po.Ratio = Aratio;
                         lpages.Add(po);
                     }
                 });

文件写入

protected static void ScaleImage(System.Drawing.Image image, int maxWidth, int maxHeight, string path, out string height, out string Aratio)
        {
            var ratio = (double)maxWidth / image.Width;
            Aratio = ratio.ToString();
            var newWidth = (int)(image.Width * ratio);
            var newHeight = (int)(image.Height * ratio);
            height = newHeight.ToString();
            //var newImage = new Bitmap(newWidth, newHeight);
            using (var newImage = new Bitmap(newWidth, newHeight))
            {
                Graphics.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight);
                using (var bmp = new Bitmap(newImage))
                {
                    bmp.Save(path, ImageFormat.Png);
                }
            }
            //newImage.Dispose();
        }

清理过程(西班牙语中的变量名)

    private static int _segundos = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["PeriodoLimpiezaTemp"].ToString());

    public static void LimpiarTemporales(string rutaTemporal = "", string mask = "*", int? segundos = null)
    {
        int time = segundos ?? _segundos;

        System.Threading.Tasks.Task.Run(
            () =>
            {
                rutaTemporal = string.IsNullOrEmpty(rutaTemporal) ? Path.GetTempPath() : rutaTemporal;
                var dInfo = new DirectoryInfo(rutaTemporal);
                var files = dInfo.GetFiles(mask);
                foreach (var file in files)
                {
                    var dif = (DateTime.Now - file.CreationTime);
                    if (dif.TotalSeconds >= time )
                    {
                        try
                        { //Intenta el eliminar los temporales. Si no puede sigue de largo.
                            file.Delete();
                        }
                        catch
                        {
                            //do nothing. Just in case some file it's been used by another process. I don't care if any file is left here, the next run may delete it.
                        }
                    }
                };
            });
    }

我想在Global.asax中使用它的地方

    protected void Session_End()
    {
        int segundos = 14400;
        LimpiarTemporales(segundos);
    }

    protected void Application_End()
    {
        LimpiarTemporales();
    }

创建临时文件的最佳方法是什么? (考虑到我必须在渲染之前创建它们……)

管理删除的最佳方法是什么?

欢迎任何建议

0 个答案:

没有答案