private void ProcessSelectedChannels(IEnumerable <Channel> aChannels, TimeInterval aTimeInterval) { try { IEnumerable <Channel> channels = aChannels.Where(x => x.IsChecked); int count = channels.Count(); if (count == 0) { return; } string destination = Path.Combine(DestinationPath, $"Export_{DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff")}"); if (!Directory.Exists(destination)) { Directory.CreateDirectory(destination); } ArchiveInfo archiveInfo = new ArchiveInfo(); // Set material file id int materialFileId = 0; // Create new material folder index MaterialFolderIndex index = new MaterialFolderIndex() { MaterialFolderId = Guid.NewGuid() }; double progress = 0; double channelProgress = 100.0 / count; var parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = 1 }; Parallel.ForEach(channels, parallelOptions, (channel) => { if (_stopTask.IsCancellationRequested) { return; } var files = channel.Records.Where(x => !ShouldSkipFile(x, aTimeInterval)).OrderBy(x => x.BeginTimestamp); double fileProgress = channelProgress / files.Count(); foreach (var fileIndexRecord in files) { if (_stopTask.IsCancellationRequested) { return; } string sourceFilePath = Path.Combine(SelectedPath, Helpers.GetFileName(fileIndexRecord.MaterialFileId)); if (File.Exists(sourceFilePath)) { var fileId = Interlocked.Increment(ref materialFileId); // Generate new file name string newFilePath = Path.Combine(destination, Helpers.GetFileName(fileId)); _logger.Info($"Source file: {sourceFilePath}, destination file: {newFilePath}"); if (File.Exists(newFilePath)) { File.SetAttributes(newFilePath, FileAttributes.Normal); File.Delete(newFilePath); } MaterialFolderIndexRecord indexRecord = new MaterialFolderIndexRecord() { ChannelId = fileIndexRecord.ChannelId, DataType = fileIndexRecord.DataType, ChannelType = ChannelType.Material, MaterialFileId = fileId }; if (ProcessFile(index.MaterialFolderId, sourceFilePath, indexRecord, aTimeInterval, newFilePath)) { lock (_indexLock) { // Update index index.IndexRecords.Add(indexRecord); // Update arhive info archiveInfo.UpdateArchiveInfo(indexRecord, new AdditionalInfo() { Name = GetChannelName(indexRecord) + " " + indexRecord.ChannelId }); // Flush index time limits indexRecord.Flush(); // Update file info archiveInfo.UpdateFileInfo(newFilePath); } } } lock (_progressLock) { progress += fileProgress; SendProgress(progress); } } }); if (index.IndexRecords.Count > 0 && !_stopTask.IsCancellationRequested) { SaveMaterialFolderIndex(index, destination); ArchiveInfo.SaveArchiveInfo(archiveInfo, destination); } } catch (Exception ex) { SendError(ex.Message); } finally { SendExportCompleted(); } }