public virtual void testConcurrentEndOfSameProcess() { IProcessInstance processInstance = runtimeService.StartProcessInstanceByKey("oneTaskWithDelay"); ITask task = taskService.CreateTaskQuery().FirstOrDefault(); Assert.NotNull(task); // We will now start two threads that both complete the task. // In the process, the task is followed by a delay of three seconds // This will cause both threads to call the taskService.Complete method with enough time, // before ending the process. Both threads will now try to end the process // and only one should succeed (due to optimistic locking). TaskCompleter taskCompleter1 = new TaskCompleter(taskService, this, task.Id); TaskCompleter taskCompleter2 = new TaskCompleter(taskService, this, task.Id); Assert.IsFalse(taskCompleter1.Succeeded); Assert.IsFalse(taskCompleter2.Succeeded); taskCompleter1.Start(); taskCompleter2.Start(); taskCompleter1.Join(); taskCompleter2.Join(); int successCount = 0; if (taskCompleter1.Succeeded) { successCount++; } if (taskCompleter2.Succeeded) { successCount++; } Assert.AreEqual(/*"(Only) one thread should have been able to successfully end the process",*/ 1, successCount); AssertProcessEnded(processInstance.Id); }
private void ExecuteLongRunningTask(ISqlConnectionResolver connectionResolver, string taskName, bool shouldFail) { // We don't use transaction - if task fails, it remains in the database, marked as incomplete var taskCreator = new TaskCreator(connectionResolver); var taskCompleter = new TaskCompleter(connectionResolver); var task = taskCreator.Create(new TaskCreatorInput { Name = taskName }); // Perfom long-running operations... if (shouldFail) { throw new InvalidOperationException("Task failed."); } taskCompleter.Complete(new TaskCompleterInput { TaskId = task.TaskId }); }