异常信息:System.OutOfMemoryException

时间:2017-09-22 12:15:30

标签: c# windows-services hangfire

我收到以下错误:

Exception Info: System.OutOfMemoryException
Stack:
   at System.Threading.ExecutionContext.CreateCopy()
   at System.Threading.Tasks.Task.CopyExecutionContext(System.Threading.ExecutionContext)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef)
   at System.Threading.Tasks.Task.ExecuteEntry(Boolean)
   at System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

该应用程序是一个c#windows服务(使用TopShelf)。该应用程序正在使用HanFire intitiate RunScan()方法。

我没有看到代码中的位置,但我怀疑它是添加到阻塞集合中。

代码:

public void RunScan(IJobCancellationToken cancellationToken, string path, int pathId)
        {


            SmartScanDAO scDAO = new SmartScanDAO();
            PathInfo RootPathInfo = scDAO.ScanStarted(pathId);
            try
            {

                if (RootPathInfo == null)
                {
                    ErrorLogger.LogEvent(RootPathInfo.Id, string.Format("Path ({1}): {0} is null", path, pathId), EventLogEntryType.Error);
                    return;
                }
                if (RootPathInfo.Status == ScanStatus.Processing)
                {
                    ErrorLogger.LogEvent(RootPathInfo.Id, string.Format("Path {0} is currently being scanned", path), EventLogEntryType.Information);
                    return;
                }
                RootPathInfo.Status = ScanStatus.Processing;
                scDAO.ScanStatus(RootPathInfo);

                ErrorLogger.LogEvent(string.Format("Scanning {0}", path), EventLogEntryType.Information);

                if (!Directory.Exists(path))
                {
                    scDAO.DisableIsilonScanPathById(RootPathInfo.Id);
                    ErrorLogger.LogEvent(RootPathInfo.Id, "The Path does not exists: " + path, EventLogEntryType.Error);
                    return;
                }

                // Get Directories to Skip
                skipPaths = scDAO.GetDuplicateIsilonScanPaths(RootPathInfo.Path);

                DirectoryInfo di = new DirectoryInfo(path);
                SplunkExport.DeleteFiles(path, new List<string>() { "acl", "path" }, RootPathInfo.Id);

                DirectoryType = (DirectoryType)Enum.Parse(typeof(DirectoryType), RootPathInfo.DirectoryType);
                RootPathInfo.Path = di.FullName.ToLower();
                RootPathInfo.Owner = GetAcl(RootPathInfo.Id, RootPathInfo.Path, DirectoryType, true, false, true);// SecurityUtils.GetOwner(di.FullName, (DirectoryType)Enum.Parse(typeof(DirectoryType), RootPathInfo.DirectoryType));
                RootPathInfo.Files = 0;
                RootPathInfo.Size = 0;

                Interlocked.Add(ref FileCount, di.GetFiles().Length);
                Interlocked.Add(ref DirectorySize, (int)di.GetFiles().Sum(f => f.Length));


                Task<List<string>> outputMetaDataTask = Task.Factory.StartNew(() => WriteOutput(RootPathInfo.Path, SplunkFileType.MetaData, MetaDataQueue), TaskCreationOptions.LongRunning);
                Task<List<string>> outputACLTask = Task.Factory.StartNew(() => WriteOutput(RootPathInfo.Path, SplunkFileType.ACL, ACLQueue), TaskCreationOptions.LongRunning);


                Action action = (() => UpdateStats(RootPathInfo.Id, MetaDataQueue, ACLQueue));

                CancellationTokenSource UpdateStatsToken = new CancellationTokenSource();
                IObservable<long> observable = Observable.Interval(TimeSpan.FromMinutes(10));
                // Subscribe the obserable to the task on execution.
                observable.Subscribe(x =>
                {
                    Task task = new Task(action); task.Start();
                    // task.ContinueWith(c => resumeAction());
                }, UpdateStatsToken.Token);

                MetaDataQueue.Add(string.Format("\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\",\"{7}\",\"{8}\"", DateTime.UtcNow + " UTC", di.FullName.ToLower(), 1, ((DirectoryInfo)di).GetFiles().Length, string.Format("{0:0.0}", ((DirectoryInfo)di).GetFiles().Sum(f => f.Length) / 1024 / 1024), RootPathInfo.Owner, di.LastAccessTimeUtc, di.CreationTimeUtc, di.LastWriteTimeUtc, ""));
                //

                // Traverse the path
                GetSystemObjects(cancellationToken, di, RootPathInfo.Id, DirectoryType);

                // Complete adding
                MetaDataQueue.CompleteAdding();
                ACLQueue.CompleteAdding();


                // wait for 
                outputMetaDataTask.Wait();
                outputACLTask.Wait();


                //Send Files to Splunk
                SplunkExport.CopyFilesToSplunk(outputMetaDataTask.Result, outputACLTask.Result, RootPathInfo.Id);

                SmartScanDAO dao = new SmartScanDAO();
                RootPathInfo.Size = DirectorySize;

            }
            catch (OperationCanceledException cex)
            {
                RootPathInfo.Status = ScanStatus.Cancelled;
                if (scDAO == null)
                    scDAO = new SmartScanDAO();
                scDAO.ScanStatus(RootPathInfo);
                ErrorLogger.LogEvent(cex, RootPathInfo.Id);
            }
            catch (Exception ex)
            {
                if (RootPathInfo == null)
                {
                    RootPathInfo = new PathInfo();
                    RootPathInfo.Id = pathId;
                }
                ErrorLogger.LogEvent(ex, RootPathInfo.Id);
                RootPathInfo.Status = ScanStatus.Error;
                if (scDAO == null)
                    scDAO = new SmartScanDAO();
                scDAO.ScanStatus(RootPathInfo);


            }

        }

        List<string> WriteOutput(string path, SplunkFileType fileType, BlockingCollection<string> queue)
        {
            var fileList = new List<string>();
            int filecount = 1;
            int linecount = 0;
            int maxlinecount = 200000;
            string header = (fileType.ToString() == SplunkFileType.ACL.ToString()?aclHeader:metaDataHeader);

            var filepattern = SplunkExport.GetPaths(path, fileType.ToString());

            string filename = string.Format(filepattern, filecount);
            fileList.Add(filename);
            while (true)
            {
                using (var strm = File.AppendText(filename))
                {
                    foreach (var s in queue.GetConsumingEnumerable())
                    {
                        if (linecount == 0)
                            strm.WriteLine(header);

                        strm.WriteLine(s);
                        // if you want to make sure it's written to disk immediately,
                        // call Flush. This will slow performance, however.
                        strm.Flush();
                        linecount++;
                        if (linecount > maxlinecount)
                        {
                            linecount = 0;
                            filecount++;
                            break;
                        }
                    }
                }
                if (queue.IsCompleted)
                    break;
                filename = string.Format(filepattern, filecount);
                fileList.Add(filename);
            }

            return fileList;
        }

        private void GetSystemObjects(IJobCancellationToken cancellationToken, DirectoryInfo di, int pathid, DirectoryType directorytype = DirectoryType.Share)
        {
            long files = 0;
            long size = 0;
            int mb = 1024 * 1024;
            try
            {

                Parallel.ForEach<FileSystemInfo>(di.EnumerateFileSystemInfos("*", System.IO.SearchOption.TopDirectoryOnly).Where(r => !r.FullName.Contains(@"\~snapshot") ), (FileSystemInfo fso) =>
                {
                    if (skipPaths.Contains(fso.FullName))
                        return;
                    if (cancellationToken != null)
                        cancellationToken.ThrowIfCancellationRequested();

                    bool isDirectory = fso.EntryInfo.IsDirectory;
                    string owner = "";

                    owner = GetAcl(pathid, fso.FullName, directorytype, isDirectory, false);
                    try
                    {

                        if (isDirectory)
                        {
                            DirectoryInfo dis = new DirectoryInfo(fso.FullName);
                            lock (lckObject)
                            { 
                                files = ((DirectoryInfo)fso).GetFiles().Length;
                                size = ((DirectoryInfo)fso).GetFiles().Sum(f => f.Length);
                            }
                            Interlocked.Add(ref FileCount, files);
                            Interlocked.Add(ref DirectorySize, size);

                            ErrorLogger.LogEvent(pathid, string.Format("Scan Directory\t{0}\t{1}", fso.FullName, files));
                        }
                        else
                        {
                            size = ((FileInfo)fso).Length;
                            files = 0;
                        }

                        MetaDataQueue.Add(string.Format("\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\",\"{7}\",\"{8}\"", DateTime.UtcNow + " UTC", fso.FullName.ToLower(), (fso.EntryInfo.IsDirectory ? 1 : 0), files, string.Format("{0:0.0}", size / mb), owner, fso.LastAccessTimeUtc, fso.CreationTimeUtc, fso.LastWriteTimeUtc));
                    }
                    catch (Exception ex)
                    {
                        ErrorLogger.LogEvent(ex, pathid);
                    }

                    if (isDirectory)
                        GetSystemObjects(cancellationToken, (DirectoryInfo)fso, pathid, directorytype);

                    fso = null;

                }); // end of ForEach
            }
            catch (Exception ex)
            {
                ErrorLogger.LogEvent(ex, pathid);
            }
        }

可能发生错误或如何更接近根本原因的任何建议。在例外情况下,我没有看到任何指示。

0 个答案:

没有答案