public void Export(CommonTimeline commonTimeline, PlayerScreen leftPlayer, PlayerScreen rightPlayer, bool merging) { this.commonTimeline = commonTimeline; this.leftPlayer = leftPlayer; this.rightPlayer = rightPlayer; this.merging = merging; // During saving we move through the common timeline by a time unit based on framerate and high speed factor, but not based on user custom slow motion factor. // For the framerate saved in the file metadata we take user custom slow motion into account and not high speed factor. fileFrameInterval = Math.Max(leftPlayer.FrameInterval, rightPlayer.FrameInterval); fileFrameInterval = Math.Max(fileFrameInterval, 10); dualSaveFileName = GetFilename(leftPlayer, rightPlayer); if (string.IsNullOrEmpty(dualSaveFileName)) { return; } dualSaveCancelled = false; // Instanciate and configure the bgWorker. bgWorkerDualSave = new BackgroundWorker(); bgWorkerDualSave.WorkerReportsProgress = true; bgWorkerDualSave.WorkerSupportsCancellation = true; bgWorkerDualSave.DoWork += bgWorkerDualSave_DoWork; bgWorkerDualSave.ProgressChanged += bgWorkerDualSave_ProgressChanged; bgWorkerDualSave.RunWorkerCompleted += bgWorkerDualSave_RunWorkerCompleted; // Make sure none of the screen will try to update itself. // Otherwise it will cause access to the other screen image (in case of merge), which can cause a crash. leftPlayer.DualSaveInProgress = true; rightPlayer.DualSaveInProgress = true; dualSaveProgressBar = new formProgressBar(true); dualSaveProgressBar.Cancel = dualSave_CancelAsked; // The worker thread runs in the background while the UI thread is in the progress bar dialog. // We only continue after these two lines once the video has been saved or the saving cancelled. bgWorkerDualSave.RunWorkerAsync(); dualSaveProgressBar.ShowDialog(); if (dualSaveCancelled) { DeleteTemporaryFile(dualSaveFileName); } leftPlayer.DualSaveInProgress = false; rightPlayer.DualSaveInProgress = false; }