public void MergeByTreeNodesAsync(
            IEnumerable<TreeNode> fileNodesToMerge,
            string mergedModName)
        {
            _bgWorker.DoWork += (sender, e) =>
            {
                _checkedFileNodes = fileNodesToMerge.ToArray();
                _mergedModName = mergedModName;

                var checkedModNodesForFile =
                    _checkedFileNodes.Select(
                        fileNode =>
                        fileNode.GetTreeNodes().Where(
                            modNode =>
                            modNode.Checked
                        ).ToArray()
                    ).ToArray();

                ProgressInfo.TotalMergeCount = checkedModNodesForFile.Sum(modNodes => modNodes.Length - 1);
                ProgressInfo.TotalFileCount = _checkedFileNodes.Length;

                for (int i = 0; i < _checkedFileNodes.Length; ++i)
                {
                    var fileNode = _checkedFileNodes[i];

                    ProgressInfo.CurrentFileName = Path.GetFileName(fileNode.Text);
                    ProgressInfo.CurrentFileNum = i + 1;

                    var checkedModNodes = checkedModNodesForFile[i];

                    ProgressInfo.CurrentAction = "Starting merge";

                    if (checkedModNodes.Any(node => (new LoadOrderComparer()).Compare(node.Text, _mergedModName) < 0) &&
                        !ConfirmRemainingConflict(_mergedModName))
                        continue;

                    var isNew = false;
                    var merge = _inventory.Merges.FirstOrDefault(m => m.RelativePath.EqualsIgnoreCase(fileNode.Text));
                    if (merge == null)
                    {
                        isNew = true;
                        merge = new Merge
                        {
                            RelativePath = fileNode.Text,
                            MergedModName = _mergedModName
                        };
                    }

                    if ((ModFileCategory)fileNode.Parent.Tag == Categories.BundleText)
                    {
                        merge.BundleName = Path.GetFileName(Paths.RetrieveMergedBundlePath());
                        MergeBundleFileNode(fileNode, checkedModNodes, merge, isNew);
                    }
                    else
                        MergeFlatFileNode(fileNode, checkedModNodes, merge, isNew);
                }
                if (_bundleChanged)
                {
                    var newBundlePath = PackNewBundle(Paths.RetrieveMergedBundlePath());
                    if (newBundlePath != null)
                    {
                        ProgressInfo.CurrentAction = "Adding bundle merge to inventory";
                        foreach (var bundleMerge in _pendingBundleMerges)
                            _inventory.Merges.Add(bundleMerge);

                        if (Program.Settings.Get<bool>("PlayCompletionSounds"))
                        {
                            System.Media.SystemSounds.Asterisk.Play();
                        }
                        if (Program.Settings.Get<bool>("ReportAfterPack"))
                        {
                            using (var reportForm = new PackReportForm(newBundlePath))
                            {
                                ProgressInfo.CurrentAction = "Showing pack report";
                                Program.MainForm.ShowModal(reportForm);
                            }
                        }
                    }
                }
                CleanUpTempFiles();
                CleanUpEmptyDirectories();
            };
            _bgWorker.RunWorkerAsync();
        }
        public void RepackBundleAsync(string bundlePath)
        {
            if (_bgWorker.IsBusy)
                throw new Exception("BackgroundWorker can't run 2 tasks concurrently.");
            _bgWorker.DoWork += (sender, e) =>
            {
                var newBundlePath = PackNewBundle(bundlePath, true);
                if (newBundlePath == null)
                    return;

                if (Program.Settings.Get<bool>("PlayCompletionSounds"))
                {
                    System.Media.SystemSounds.Asterisk.Play();
                }
                if (Program.Settings.Get<bool>("ReportAfterPack"))
                {
                    using (var reportForm = new PackReportForm(bundlePath))
                    {
                        Program.MainForm.ShowModal(reportForm);
                    }
                }
            };
            _bgWorker.RunWorkerAsync();
        }