public static void TestObjectDisposedException() { ThreadWorker worker = new ThreadWorker(new ProgressContext()); worker.Work += (object sender, ThreadWorkerEventArgs e) => { e.Result = FileOperationStatus.Success; }; try { worker.Run(); worker.Join(); } finally { worker.Dispose(); } bool hasCompleted = false; Assert.Throws <ObjectDisposedException>(() => { worker.Run(); }); Assert.Throws <ObjectDisposedException>(() => { worker.Join(); }); Assert.Throws <ObjectDisposedException>(() => { hasCompleted = worker.HasCompleted; }); Assert.That(!hasCompleted, "Although the thread has completed, the variable should still be false since the attempt to set it is after Dispose()."); Assert.DoesNotThrow(() => { worker.Dispose(); }); }
public void Decrypt(Passphrase passphrase) { BTProgressHUD.Show("Opening ...", maskType: BTProgressHUD.MaskType.Gradient); CreateWorker(); this.key = passphrase.DerivedPassphrase; worker.Run(); }
public static void TestProgress() { FakeRuntimeEnvironment environment = (FakeRuntimeEnvironment)OS.Current; int progressCalls = 0; ProgressContext progress = new ProgressContext(); using (ThreadWorker worker = new ThreadWorker(progress)) { worker.Work += (object sender, ThreadWorkerEventArgs e) => { environment.CurrentTiming.CurrentTiming = TimeSpan.FromSeconds(1); e.Progress.AddCount(1); e.Result = FileOperationStatus.Success; }; progress.Progressing += (object sender, ProgressEventArgs e) => { ++progressCalls; }; worker.Run(); worker.Join(); } Assert.That(progressCalls, Is.EqualTo(1), "The Progressing event should be raised exactly one time."); }
public static void TestSimple() { int workThreadId = -1; FileOperationStatus returnedStatus = FileOperationStatus.UnspecifiedError; bool done = false; using (ThreadWorker worker = new ThreadWorker(new ProgressContext())) { worker.Work += (object sender, ThreadWorkerEventArgs e) => { workThreadId = Thread.CurrentThread.ManagedThreadId; e.Result = FileOperationStatus.Success; }; worker.Completing += (object sender, ThreadWorkerEventArgs e) => { returnedStatus = e.Result; done = true; }; worker.Run(); worker.Join(); } Assert.That(returnedStatus, Is.EqualTo(FileOperationStatus.Success), "The status should be returned as successful."); Assert.That(workThreadId, Is.Not.EqualTo(Thread.CurrentThread.ManagedThreadId), "The work should not be performed on the caller thread."); Assert.That(done, Is.True, "The background work must have executed the completed handler now."); }
public static void TestFinishInBackground() { bool didComplete = false; ProgressContext progress = new ProgressContext(); progress.Progressing += (object sender2, ProgressEventArgs e2) => { didComplete = true; }; using (ThreadWorker threadWorker = new ThreadWorker(progress)) { threadWorker.Work += (object sender, ThreadWorkerEventArgs e) => { using (WorkerGroup workerGroup = new WorkerGroup(progress)) { IThreadWorker worker = workerGroup.CreateWorker(); worker.Work += (object sender2, ThreadWorkerEventArgs e2) => { e2.Progress.NotifyLevelStart(); e2.Progress.NotifyLevelFinished(); }; worker.Run(); } }; threadWorker.Run(); } Assert.That(didComplete, "Execution should continue here, with the flag set indicating that the progress event occurred."); }
private void StartNotifyWorker() { lock (NoticeLocker) { if (!NotifyWorker.IsRunning) { NotifyWorker.Run(); } NotifyWorker.DoWorkAction = this.DoNotify; NotifyWorker.Interval = TimelineSettings.Instance.NotifyInterval; isNotifyRunning = true; } }
public static void TestPrepare() { bool wasPrepared = false; using (ThreadWorker worker = new ThreadWorker(new ProgressContext())) { worker.Prepare += (object sender, ThreadWorkerEventArgs e) => { wasPrepared = true; }; worker.Run(); worker.Join(); } Assert.That(wasPrepared, Is.True, "The Prepare event should be raised."); }
public void Initialize() { if (this.isInitialized) { return; } this.isInitialized = true; lock (this) { this.scanWorker = ThreadWorker.Run( this.ScanEnmity, 100d, "ScanEnmityWorker", ThreadPriority.BelowNormal); } }
public static void TestErrorSetInWorkCompleted() { bool errorInWork = false; using (ThreadWorker worker = new ThreadWorker(new ProgressContext())) { worker.Work += (object sender, ThreadWorkerEventArgs e) => { throw new InvalidOperationException(); }; worker.Completing += (object sender, ThreadWorkerEventArgs e) => { errorInWork = e.Result == FileOperationStatus.Exception; }; worker.Run(); worker.Join(); } Assert.That(errorInWork, Is.True, "The operation was interrupted by an exception and should return status as such."); }
public static void TestCancellationByException() { bool wasCanceled = false; using (ThreadWorker worker = new ThreadWorker(new ProgressContext())) { worker.Work += (object sender, ThreadWorkerEventArgs e) => { throw new OperationCanceledException(); }; worker.Completing += (object sender, ThreadWorkerEventArgs e) => { wasCanceled = e.Result == FileOperationStatus.Canceled; }; worker.Run(); worker.Join(); } Assert.That(wasCanceled, Is.True, "The operation was canceled and should return status as such."); }
public static void TestHasCompleted() { using (ThreadWorker worker = new ThreadWorker(new ProgressContext())) { bool wasCompletedInWork = false; worker.Work += (object sender, ThreadWorkerEventArgs e) => { wasCompletedInWork = worker.HasCompleted; }; bool wasCompletedInCompleted = false; worker.Completing += (object sender, ThreadWorkerEventArgs e) => { wasCompletedInCompleted = worker.HasCompleted; }; worker.Run(); worker.Join(); Assert.That(!wasCompletedInWork, "Completion is not set as true in the work event."); Assert.That(!wasCompletedInCompleted, "Completion is not set as true until after the completed event."); Assert.That(worker.HasCompleted, "Completion should be set as true when the thread is joined."); } }
/// <summary> /// Perform a background operation with support for progress bars and cancel. /// </summary> /// <param name="displayText">A text that may be used as a reference in various messages.</param> /// <param name="work">A 'work' delegate, taking a ProgressContext and return a FileOperationStatus. Executed on a background thread. Not the calling/GUI thread.</param> /// <param name="complete">A 'complete' delegate, taking the final status. Executed on the original caller thread, typically the GUI thread.</param> public void BackgroundWorkWithProgress(Func <ProgressContext, FileOperationStatus> work, Action <FileOperationStatus> complete) { ProgressContext progress = new ProgressContext(); ProgressBar progressBar = CreateProgressBar(progress); OnProgressBarCreated(new ControlEventArgs(progressBar)); progress.Progressing += (object sender, ProgressEventArgs e) => { progressBar.Value = e.Percent; }; ThreadWorker threadWorker = new ThreadWorker(progress); threadWorker.Work += (object sender, ThreadWorkerEventArgs e) => { e.Result = work(e.Progress); }; threadWorker.Completing += (object sender, ThreadWorkerEventArgs e) => { try { complete(e.Result); progressBar.Parent = null; } finally { progressBar.Dispose(); } }; threadWorker.Completed += (object sender, ThreadWorkerEventArgs e) => { IDisposable disposable = sender as IDisposable; if (disposable != null) { disposable.Dispose(); } Interlocked.Decrement(ref _workerCount); }; Interlocked.Increment(ref _workerCount); threadWorker.Run(); }
public static void TestCancellationByRequest() { bool wasCanceled = false; FakeRuntimeEnvironment environment = (FakeRuntimeEnvironment)OS.Current; using (ThreadWorker worker = new ThreadWorker(new ProgressContext())) { worker.Work += (object sender, ThreadWorkerEventArgs e) => { e.Progress.Cancel = true; environment.CurrentTiming.CurrentTiming = TimeSpan.FromSeconds(1); e.Progress.AddCount(1); }; worker.Completing += (object sender, ThreadWorkerEventArgs e) => { wasCanceled = e.Result == FileOperationStatus.Canceled; }; worker.Run(); worker.Join(); } Assert.That(wasCanceled, Is.True, "The operation was canceled and should return status as such."); }
private void InitTask() { this.dumpLogTask = ThreadWorker.Run( doWork, TimeSpan.FromSeconds(Config.Instance.WriteInterval).TotalMilliseconds, "XIVLog Worker", ThreadPriority.Lowest); ActGlobals.oFormActMain.OnLogLineRead -= this.OnLogLineRead; ActGlobals.oFormActMain.OnLogLineRead += this.OnLogLineRead; void doWork() { var isNeedsFlush = false; if (string.IsNullOrEmpty(Config.Instance.OutputDirectory) || LogQueue.IsEmpty) { Thread.Sleep(TimeSpan.FromSeconds(Config.Instance.WriteInterval)); return; } if ((DateTime.Now - this.lastFlushTimestamp).TotalSeconds >= Config.Instance.FlushInterval) { isNeedsFlush = true; } if (this.currentLogfileName != this.LogfileName) { if (this.writter != null) { if (this.writeBuffer.Length > 0) { this.writter.Write(this.writeBuffer.ToString()); this.writeBuffer.Clear(); } this.writter.Flush(); this.writter.Close(); this.writter.Dispose(); } if (!Directory.Exists(Config.Instance.OutputDirectory)) { Directory.CreateDirectory(Config.Instance.OutputDirectory); } this.writter = new StreamWriter( new FileStream( this.LogfileName, FileMode.Append, FileAccess.Write, FileShare.Read), new UTF8Encoding(false)); this.currentLogfileName = this.LogfileName; this.RaisePropertyChanged(nameof(this.LogfileName)); this.RaisePropertyChanged(nameof(this.LogfileNameWithoutParent)); } XIVLog.RefreshPCNameDictionary(); while (LogQueue.TryDequeue(out XIVLog xivlog)) { if (this.currentZoneName != xivlog.ZoneName) { this.currentZoneName = xivlog.ZoneName; this.wipeoutCounter = 1; this.fileNo++; isNeedsFlush = true; } if (xivlog.Log.Contains("wipeout") || xivlog.Log.Contains("の攻略を終了した。")) { this.wipeoutCounter++; this.fileNo++; isNeedsFlush = true; } this.writeBuffer.AppendLine(xivlog.ToCSVLine()); Thread.Yield(); } if (isNeedsFlush || this.isForceFlush || this.writeBuffer.Length > 5000) { this.writter.Write(this.writeBuffer.ToString()); this.writeBuffer.Clear(); if (isNeedsFlush || this.isForceFlush) { this.isForceFlush = false; this.lastFlushTimestamp = DateTime.Now; this.writter?.Flush(); } } } }
private void InitTask() { // FFXIV.Framework.config を読み込ませる lock (FFXIV.Framework.Config.ConfigBlocker) { _ = FFXIV.Framework.Config.Instance; } var config = Config.Instance; // WriteIntervalの初期値をマイグレーションする if (config.WriteInterval >= 30) { config.WriteInterval = Config.WriteIntervalDefault; } this.dumpLogTask = ThreadWorker.Run( doWork, TimeSpan.FromSeconds(config.WriteInterval).TotalMilliseconds, "XIVLog Worker", ThreadPriority.Lowest); ActGlobals.oFormActMain.OnLogLineRead -= this.OnLogLineRead; ActGlobals.oFormActMain.OnLogLineRead += this.OnLogLineRead; void doWork() { var isNeedsFlush = false; if (string.IsNullOrEmpty(config.OutputDirectory)) { Thread.Sleep(TimeSpan.FromSeconds(config.WriteInterval)); return; } if (LogQueue.IsEmpty) { if ((DateTime.Now - this.lastWroteTimestamp).TotalSeconds > 10) { this.lastWroteTimestamp = DateTime.MaxValue; isNeedsFlush = true; } else { if (!this.isForceFlush) { Thread.Sleep(TimeSpan.FromSeconds(config.WriteInterval)); return; } } } if ((DateTime.Now - this.lastFlushTimestamp).TotalSeconds >= config.FlushInterval) { isNeedsFlush = true; } if (this.currentLogfileName != this.LogfileName) { if (this.writter != null) { this.writter.Flush(); this.writter.Close(); this.writter.Dispose(); } if (!Directory.Exists(config.OutputDirectory)) { Directory.CreateDirectory(config.OutputDirectory); } this.writter = new StreamWriter( new FileStream( this.LogfileName, FileMode.Append, FileAccess.Write, FileShare.Read, 64 * 1024), new UTF8Encoding(config.WithBOM)); this.currentLogfileName = this.LogfileName; this.RaisePropertyChanged(nameof(this.LogfileName)); this.RaisePropertyChanged(nameof(this.LogfileNameWithoutParent)); } XIVLog.RefreshPCNameDictionary(); while (LogQueue.TryDequeue(out XIVLog xivlog)) { if (this.currentZoneName != xivlog.ZoneName) { this.currentZoneName = xivlog.ZoneName; this.wipeoutCounter = 1; this.fileNo++; isNeedsFlush = true; } if (StopLoggingKeywords.Any(x => xivlog.Log.Contains(x))) { this.wipeoutCounter++; this.fileNo++; isNeedsFlush = true; } // ログをParseする xivlog.Parse(); this.writter.WriteLine(xivlog.ToCSVLine()); this.lastWroteTimestamp = DateTime.Now; Thread.Yield(); } if (isNeedsFlush || this.isForceFlush) { if (isNeedsFlush || this.isForceFlush) { this.isForceFlush = false; this.lastFlushTimestamp = DateTime.Now; this.writter?.Flush(); } } } }