/// <summary>Called by a runner process to signal end of job</summary> /// <param name="sender">The sender</param> /// <param name="args">The command arguments</param> private void OnEndJob(object sender, SocketServer.CommandArgs args) { try { EndJobArguments arguments = args.obj as EndJobArguments; JobCompleteArgs jobCompleteArguments = new JobCompleteArgs(); jobCompleteArguments.job = runningJobs[arguments.key]; if (arguments.errorMessage != null) { jobCompleteArguments.exceptionThrowByJob = new Exception(arguments.errorMessage); } lock (this) { if (JobCompleted != null) { JobCompleted.Invoke(this, jobCompleteArguments); } runningJobs.Remove(arguments.key); } server.Send(args.socket, "OK"); } catch (Exception err) { errors += err.ToString() + Environment.NewLine; } }
public void TestNullDirPathInJob() { sut.EmulateServiceStart(null); List <ExecutablePackage> packages = new List <ExecutablePackage>(); ExecutablePackage package = new ExecutablePackage("mock.xml", null, "TestJobManager.dll", "TestJobManager.MockJobRunner", new SerializableDictionary <string, string>(), new SerializableDictionary <string, string>()); packages.Add(package); Job j1 = new Job("nobuildpath", "MockVMConfig1", new SerializableDictionary <string, string>(), packages, new SerializableDictionary <string, string>()); MessageSendRecieve msr = new MessageSendRecieve(new DirectoryInfo(inboxPath), new DirectoryInfo(outboxPath)); DateTime queuedJobsDateTime = DateTime.Now; string job1msgID = msr.QueueJob(j1); //wait for job completion JobCompleted jobCompleted = msr.WaitForJobCompletion(job1msgID, DEFAULT_WAIT); sut.EmulateServiceStop(); Assert.That(jobCompleted, Is.Not.Null); Assert.That(jobCompleted.Job, Is.Not.Null); Assert.That(jobCompleted.Result, Is.Not.Null); Assert.That(jobCompleted.Result.Errors, Is.Not.Empty); VerifyStringInList(jobCompleted.Result.Errors, "Exception: Value cannot be null.\nParameter name: path"); VerifyAppLogDoesNotContain(EventLogEntryType.Warning, testStart); VerifyAppLogDoesNotContain(EventLogEntryType.Error, testStart); }
private void Bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { this.progBar.Visibility = System.Windows.Visibility.Collapsed; JobCompleted Jc = (JobCompleted)e.Result; this.tblStatus.Text = "Updated " + Jc.CountUpdatedRecords.ToString("#,##0") + " records"; UpdateCount += (int)Jc.CountUpdatedRecords; if (Jc.IsImport) { Bgw.DoWork -= Bgw_DoWorkImport; } else { Bgw.DoWork -= Bgw_DoWorkExport; } Bgw.ProgressChanged -= Bgw_ProgressChanged; Bgw.RunWorkerCompleted -= Bgw_RunWorkerCompleted; // reset interface this.stackUpdateFields.Children.Clear(); this.dockInterface.IsEnabled = true; this.dockProgBar.IsEnabled = true; }
private async Task FinishOutput(BuildState buildState, JobCompletedEventArgs jobCompletedEventArgs) { if (buildOutputStream != null) { await buildOutputStream.FlushAsync(); buildOutputStream.Flush(flushToDisk: true); await buildOutputStream.DisposeAsync(); } int extraChars = outputDecoder.GetCharCount(Array.Empty <byte>(), 0, 0, flush: true); if (extraChars > 0) { var decoded = new char[extraChars]; outputDecoder.GetChars(Array.Empty <byte>(), 0, 0, decoded, 0, flush: true); AppendLineChars(decoded); } await FileUtil.WriteAllTextToDiskAsync( Path.Combine(buildDir, "result.json"), JsonConvert.SerializeObject(new JobBuildResult { State = buildState, }), Encoding.UTF8, CancellationToken.None ); outputLines.Add(currentLine.ToString()); OutputLinesChanged?.Invoke(this, new OutputLinesChangedEventArgs(outputLines)); state = buildState; complete.TrySetResult(null); JobCompleted?.Invoke(this, jobCompletedEventArgs); }
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // First, handle the case where an exception was thrown. if (e.Error != null) { // MessageBox.Show(e.Error.Message); } else if (e.Cancelled) { // Next, handle the case where the user canceled // the operation. // Note that due to a race condition in // the DoWork event handler, the Cancelled // flag may not have been set, even though // CancelAsync was called. // resultLabel.Text = "Canceled"; } else { // Finally, handle the case where the operation // succeeded. // resultLabel.Text = e.Result.ToString(); } JobCompleted?.Invoke(sender, e); // Enable the UpDown control. }
protected async void FireJobCompleted(JobEventArgs jobEventArgs) { var dispatcher = CoreApplication.MainView.CoreWindow.Dispatcher; await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { JobCompleted?.Invoke(this, jobEventArgs); }); }
/// <summary> /// Returns the result from the JobCompleted event /// </summary> /// <typeparam name="T"></typeparam> /// <param name="source"></param> /// <returns></returns> public static T GetResult <T>(this JobCompleted source) { if (source == null) { throw new ArgumentNullException(nameof(source)); } return(ObjectTypeDeserializer.Deserialize <T>(source.Results)); }
public void TestNullISOs() { sut.EmulateServiceStart(null); DirectoryInfo tempDir = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "tempdll")); tempDir.Create(); try { List <ExecutablePackage> packages = new List <ExecutablePackage>(); ExecutablePackage package = new ExecutablePackage("mock.xml", tempDir.FullName, "TestJobManager.dll", "TestJobManager.MockJobRunner", new SerializableDictionary <string, string>(), new SerializableDictionary <string, string>()); packages.Add(package); Job j1 = new Job(null, "MockVMConfig1", null, packages, new SerializableDictionary <string, string>()); MessageSendRecieve msr = new MessageSendRecieve(new DirectoryInfo(inboxPath), new DirectoryInfo(outboxPath)); DateTime queuedJobsDateTime = DateTime.Now; string job1msgID = msr.QueueJob(j1); //wait for job 1 to start Assert.True(WaitForVMAction(vmHash["MockVMName1"], VMActionType.Start, queuedJobsDateTime, TimeSpan.FromSeconds(5))); //send request for job 1 AutomationMessage m = new AutomationMessage(new SimpleRequest(SimpleRequests.JobRequest)); m.From = "MockVMName1"; Job j = msr.WaitForJob(msr.Send(m), DEFAULT_WAIT); Assert.That(j, Is.Not.Null); Assert.That(j.JobID, Is.EqualTo(j1.JobID)); //send finished for job 1 DateTime finishedSentDateTime = DateTime.Now; JobResult jr = new JobResult(); jr.Completed = true; ExecutionResult er = new ExecutionResult(); er.Success = true; jr.ExecutionResults.Add(er); msr.ReportJobStatus(new JobCompleted(j1, jr)); //wait for job completion JobCompleted jobCompleted = msr.WaitForJobCompletion(job1msgID, DEFAULT_WAIT); sut.EmulateServiceStop(); VerifyAppLogDoesNotContain(EventLogEntryType.Warning, testStart); VerifyAppLogDoesNotContain(EventLogEntryType.Error, testStart); Assert.That(jobCompleted, Is.Not.Null); Assert.That(jobCompleted.Job, Is.Not.Null); Assert.That(jobCompleted.Result, Is.Not.Null); Assert.That(jobCompleted.Result.Errors, Is.Empty); Assert.That(jobCompleted.Result.Success, Is.True); Assert.That(jobCompleted.Result.Completed, Is.True); } finally { tempDir.Delete(true); } }
/// <summary> /// Invoke the job completed event. /// </summary> /// <param name="job"></param> /// <param name="jobManager"></param> /// <param name="startTime"></param> /// <param name="error"></param> protected void InvokeJobCompleted(IRunnable job, IJobManager jobManager, DateTime startTime, Exception error) { var finishTime = DateTime.Now; var arguments = new JobCompleteArguments() { Job = job, ExceptionThrowByJob = error, ElapsedTime = finishTime - startTime }; jobManager.JobHasCompleted(arguments); JobCompleted?.Invoke(this, arguments); }
/// <summary> /// Create a new job that can be executed by minions /// </summary> /// <param name="location">The location of the job</param> /// <param name="timeToComplete">How long it takes for minions to complete this task</param> /// <param name="jobCompletion">The method to run when the job is completed</param> public Job(Vector2 location, float timeToComplete, JobCompleted jobCompletion = null) { Location = location; TimeToComplete = timeToComplete; if (jobCompletion == null) { OnJobCompleted += () => { Owner.CurrentJob = null; } } ; else { OnJobCompleted += jobCompletion; } }
public void OnJobCompleted(JobInfo job, bool notifyUser = false) { using var scope = scopeFactory.CreateScope(); using var dataContext = scope.ServiceProvider.GetRequiredService <DataContext>(); job.State = JobState.Completed; job.Completed = DateTimeOffset.UtcNow; dataContext.SaveChanges(); userLogger.LogInfo("Job completed", userId: job.UserId, jobId: job.Id); JobCompleted?.Invoke(this, new JobCompletedEventArgs() { Job = job }); }
public bool Execute() { var startTime = DateTime.Now; try { m_CurrentCancellationToken = new CancellationTokenSource(); var cancellationToken = m_CurrentCancellationToken.Token; using (var prg = m_App.CreateProgress()) { LogMessage("Preparing job"); var jobItems = PrepareJob(); JobSet?.Invoke(jobItems, startTime); for (int i = 0; i < jobItems.Length; i++) { cancellationToken.ThrowIfCancellationRequested(); var jobItem = jobItems[i]; prg.SetStatus($"Processing {jobItem.FilePath}"); var res = TryProcessFile(jobItem, cancellationToken); ProgressChanged?.Invoke(jobItem, res); prg.Report((double)(i + 1) / (double)jobItems.Length); } } return(true); } catch (OperationCanceledException) { throw new JobCancelledException(); } catch (Exception ex) { m_Logger.Log(ex); return(false); } finally { JobCompleted?.Invoke(DateTime.Now - startTime); } }
/// <summary>Run the specified jobs</summary> /// <param name="jobs">An instance of a class that manages all jobs.</param> /// <param name="wait">Wait until all jobs finished before returning?</param> /// <param name="numberOfProcessors">The maximum number of cores to use.</param> public void Run(IJobManager jobs, bool wait = false, int numberOfProcessors = -1) { // No - get another job to run. IRunnable job = jobs.GetNextJobToRun(); CancellationTokenSource cancelToken = new CancellationTokenSource(); // Iterate through all jobs and run them. while (job != null) { JobCompleteArgs jobCompleteArguments = new JobCompleteArgs(); jobCompleteArguments.job = job; try { job.Run(cancelToken); } catch (Exception err) { jobCompleteArguments.exceptionThrowByJob = err; } if (JobCompleted != null) { JobCompleted.Invoke(this, jobCompleteArguments); } job = jobs.GetNextJobToRun(); } Exception exceptionThrown = null; try { jobs.Completed(); } catch (Exception err) { exceptionThrown = err; } if (AllJobsCompleted != null) { AllJobsCompleted.Invoke(this, new AllCompletedArgs() { exceptionThrown = exceptionThrown }); } }
/// <summary>Main DoWork method for the scheduler thread. NB this does NOT run on the UI thread. /// </summary> /// <param name="jobs">An instance of a class that manages all jobs.</param> private void JobRunnerThread(IJobManager jobs) { // No - get another job to run. IRunnable job = jobs.GetNextJobToRun(); Exception exceptionThrown = null; try { // Iterate through all jobs and run them. while (job != null && !cancelToken.IsCancellationRequested) { JobCompleteArgs jobCompleteArguments = new JobCompleteArgs(); jobCompleteArguments.job = job; try { job.Run(cancelToken); } catch (Exception err) { jobCompleteArguments.exceptionThrowByJob = err; } if (JobCompleted != null) { JobCompleted.Invoke(this, jobCompleteArguments); } job = jobs.GetNextJobToRun(); } jobs.Completed(); } catch (Exception err) { exceptionThrown = err; } allJobsFinished = true; AllJobsCompleted?.Invoke(this, new AllCompletedArgs() { exceptionThrown = exceptionThrown }); }
public void TestNullPackageList() { sut.EmulateServiceStart(null); Job j1 = new Job("nobuildpath", "MockVMConfig1", new SerializableDictionary <string, string>(), null, new SerializableDictionary <string, string>()); MessageSendRecieve msr = new MessageSendRecieve(new DirectoryInfo(inboxPath), new DirectoryInfo(outboxPath)); DateTime queuedJobsDateTime = DateTime.Now; string job1msgID = msr.QueueJob(j1); //wait for job completion JobCompleted jobCompleted = msr.WaitForJobCompletion(job1msgID, DEFAULT_WAIT); sut.EmulateServiceStop(); VerifyAppLogDoesNotContain(EventLogEntryType.Warning, testStart); VerifyAppLogDoesNotContain(EventLogEntryType.Error, testStart); Assert.That(jobCompleted, Is.Not.Null); Assert.That(jobCompleted.Job, Is.Not.Null); Assert.That(jobCompleted.Result, Is.Not.Null); Assert.That(jobCompleted.Result.Errors, Is.Not.Empty); VerifyStringInList(jobCompleted.Result.Errors, "Job does not have any packages defined"); }
public void TestNullConfiguration() { sut.EmulateServiceStart(null); Job j1 = new Job("abc", null, new SerializableDictionary <string, string>(), new List <ExecutablePackage>(), new SerializableDictionary <string, string>()); MessageSendRecieve msr = new MessageSendRecieve(new DirectoryInfo(inboxPath), new DirectoryInfo(outboxPath)); DateTime queuedJobsDateTime = DateTime.Now; string job1msgID = msr.QueueJob(j1); //wait for job completion JobCompleted jobCompleted = msr.WaitForJobCompletion(job1msgID, DEFAULT_WAIT); sut.EmulateServiceStop(); VerifyAppLogDoesNotContain(EventLogEntryType.Warning, testStart); VerifyAppLogDoesNotContain(EventLogEntryType.Error, testStart); Assert.That(jobCompleted, Is.Not.Null); Assert.That(jobCompleted.Job, Is.Not.Null); Assert.That(jobCompleted.Result, Is.Not.Null); Assert.That(jobCompleted.Result.Errors, Is.Not.Empty); VerifyStringInList(jobCompleted.Result.Errors, "Configuration cannot be null or empty"); }
public Task <bool> ExecuteAsync() { var startTime = DateTime.Now; try { using (var prg = m_App.CreateProgress()) { LogMessage("Preparing job"); var jobItems = PrepareJob(); JobSet?.Invoke(jobItems, startTime); for (int i = 0; i < jobItems.Length; i++) { var jobItem = jobItems[i]; prg.SetStatus($"Processing {jobItem.FilePath}"); var res = TryProcessFile(jobItem, default); ProgressChanged?.Invoke(jobItem, res); prg.Report((double)i / (double)jobItems.Length); } } return(Task.FromResult(true)); } catch { return(Task.FromResult(false)); } finally { JobCompleted?.Invoke(DateTime.Now - startTime); } }
protected virtual void OnJobCompleted(Worker worker, Job job) { JobCompleted?.Invoke(worker, job); }
public async Task ExecuteAsync(JobCompleted message) { await Task.Delay(0); _logger.LogInformation($"Executing {nameof(JobCompletedHandler)}: {JsonConvert.SerializeObject(message)}"); }
/// <summary>Main DoWork method for the scheduler thread. NB this does NOT run on the UI thread. /// </summary> /// <param name="jobs">An instance of a class that manages all jobs.</param> /// <param name="numberOfTasksToUse">The number of tasks to run asyhchronously</param> private void JobRunnerThread(IJobManager jobs, int numberOfTasksToUse = -1) { Exception exceptionThrown = null; try { numberTasksRunning = 0; // Main worker thread for keeping jobs running while (!cancelToken.IsCancellationRequested) { // Have we reached our maximum number of running jobs? if (numberTasksRunning >= numberOfTasksToUse) { Thread.Sleep(200); // Yes } else { // No - get another job to run. IRunnable job = jobs.GetNextJobToRun(); // If no job available then exit - we're done. if (job == null) { break; } // If the job is computationally intensive and will potentially take some time // to run, then we want to keep track of how many of these are running. if (typeof(IComputationalyTimeConsuming).IsAssignableFrom(job.GetType())) { lock (this) numberTasksRunning++; } // Run the job. Task.Run(() => { JobCompleteArgs jobCompleteArguments = new JobCompleteArgs(); jobCompleteArguments.job = job; try { job.Run(cancelToken); } catch (Exception err) { jobCompleteArguments.exceptionThrowByJob = err; } if (JobCompleted != null) { JobCompleted.Invoke(this, jobCompleteArguments); } lock (this) numberTasksRunning--; }); } } // All jobs now completed while (numberTasksRunning > 0) { Thread.Sleep(200); } jobs.Completed(); } catch (Exception err) { exceptionThrown = err; } if (AllJobsCompleted != null) { AllJobsCompleted.Invoke(this, new AllCompletedArgs() { exceptionThrown = exceptionThrown }); } }
protected virtual void OnJobCompleted(JobCompletedEventArgs e) => JobCompleted?.Invoke(this, e);
private void OnJobCompleted(JobCompletedEventArgs eventArgs) => JobCompleted?.Invoke(this, eventArgs);
public static void OnJobCompleted(object sender, JobStatus e) { JobCompleted?.Invoke(sender, e); }
/// <summary>Main DoWork method for the scheduler thread. NB this does NOT run on the UI thread. /// </summary> /// <param name="jobs">An instance of a class that manages all jobs.</param> /// <param name="numberOfTasksToUse">The number of tasks to run asyhchronously</param> private void JobRunnerThread(IJobManager jobs, int numberOfTasksToUse = -1) { Exception exceptionThrown = null; try { int numberTasksRunning = 0; // Main worker thread for keeping jobs running while (!cancelToken.IsCancellationRequested) { // Have we reached our maximum number of running jobs? if (numberTasksRunning >= numberOfTasksToUse) { Thread.Sleep(200); // Yes } else { // No - get another job to run. IRunnable job = jobs.GetNextJobToRun(); // If no job available then exit - we're done. if (job == null) { break; } lock (this) numberTasksRunning++; // Run the job. Task.Run(() => { JobCompleteArgs jobCompleteArguments = new JobCompleteArgs(); jobCompleteArguments.job = job; try { job.Run(cancelToken); } catch (Exception err) { jobCompleteArguments.exceptionThrowByJob = err; } if (JobCompleted != null) { JobCompleted.Invoke(this, jobCompleteArguments); } lock (this) numberTasksRunning--; }); } } // All jobs now completed while (numberTasksRunning > 0) { Thread.Sleep(200); } jobs.Completed(); } catch (Exception err) { exceptionThrown = err; } if (AllJobsCompleted != null) { AllJobsCompleted.Invoke(this, new AllCompletedArgs() { exceptionThrown = exceptionThrown }); } }
private void OnJobCompleted(TimeSpan duration) => JobCompleted?.Invoke(duration);
protected virtual void OnJobCompleted(object sender, EventArgs e) { JobCompleted?.Invoke(sender, e); }
public void InvokeJobCompleted(TranslationJob job) { JobCompleted?.Invoke(job); }
private void ReceiveLoop() { try { while (true) { //check to see if we need to stop if (mainLoopRunning == false) { break; } List <AutomationMessage> newMessages = new List <AutomationMessage>(); lock (IncomingQueueLock) { while (incoming.Count > 0) { newMessages.Add(incoming.Dequeue()); } } bool updateJobs = false; foreach (AutomationMessage m in newMessages) { try { if (m.Content is JobCreate) { //add job Job j = ((JobCreate)m.Content).j; JobStatus js = new JobStatus(); if (j.ISOs == null) { j.ISOs = new SerializableDictionary <string, string>(); } if (j.Properties == null) { j.Properties = new SerializableDictionary <string, string>(); } lock (JobsDictLock) { jobs[j] = js; //check required fields if (String.IsNullOrEmpty(j.Configuration)) { js.ErrorOut("Configuration cannot be null or empty", null, null); } else if (vmMap.ContainsKey(j.Configuration)) { //set the VM path for visibility to jobmanagerconsole jobs[j].VMPath = vmMap[j.Configuration].Identifier; } } updateJobs = true; } else if (m.Content is SimpleRequest) { SimpleRequest srm = (SimpleRequest)m.Content; if (srm.Request == SimpleRequests.JobRequest) { lock (JobsDictLock) { bool found = false; foreach (Job j in jobs.Keys) { JobStatus js = jobs[j]; if (js.State == JobStates.VMStarted) { VirtualMachine vm = vmMap[j.Configuration]; if (vm.IsSameHost(m.From)) { AutomationMessage toSend = new AutomationMessage(vm.HostName, m.Id, new JobReturn(j)); SendToHost(toSend); found = true; js.State = JobStates.AutoStarted; break; } } } if (!found) { AutomationMessage toSend = new AutomationMessage(m.From, m.Id, new ErrorMessage(ErrorMessage.ERROR_NO_JOB_FOUND)); SendToHost(toSend); } } } else if (srm.Request == SimpleRequests.AllVMRequest) { try { AutomationMessage toSend = new AutomationMessage(m.From, m.Id, new VMRequestReturn(vmHost.AllVMIdentifiers.ToArray(), lockedVMs.ToArray())); SendToHost(toSend); } catch (Exception ex) { EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error); AutomationMessage toSend = new AutomationMessage(m.From, m.Id, new ErrorMessage(ex.ToString())); SendToHost(toSend); } } else if (srm.Request == SimpleRequests.JobReport) { lock (JobsDictLock) { AutomationMessage toSend = new AutomationMessage(m.From, m.Id, new JobReportReturn(jobs)); SendToHost(toSend); } } } else if (m.Content is JobCompleted) { JobCompleted jcm = (JobCompleted)m.Content; lock (JobsDictLock) { foreach (Job j in jobs.Keys) { if (j.JobID == jcm.Job.JobID) { JobStatus js = jobs[j]; js.Result = jcm.Result; js.State = JobStates.AutoFinished; updateJobs = true; } } } } else if (m.Content is JobCancelCommand) { JobCancelCommand jcm = (JobCancelCommand)m.Content; lock (JobsDictLock) { foreach (Job j in jobs.Keys) { if (j.JobID == jcm.JobID) { JobStatus js = jobs[j]; js.ErrorOut("Job was canceled by user", null, null); updateJobs = true; break; } } } } else if (m.Content is JobDeleteCommand) { JobDeleteCommand jdm = (JobDeleteCommand)m.Content; lock (JobsDictLock) { Job toDelete = null; foreach (Job j in jobs.Keys) { if (j.JobID == jdm.JobID) { toDelete = j; break; } } if (toDelete != null) { jobs.Remove(toDelete); } } } else if (m.Content is LockVMCommand) { LockVMCommand cmd = (LockVMCommand)m.Content; if (!lockedVMs.Contains(cmd.VMPath)) { lockedVMs.Add(cmd.VMPath); } } else if (m.Content is UnLockVMCommand) { UnLockVMCommand cmd = (UnLockVMCommand)m.Content; if (lockedVMs.Contains(cmd.VMPath)) { lockedVMs.Remove(cmd.VMPath); } } else { EventLog.WriteEntry("Unknown message type " + m.Content.GetType().ToString(), EventLogEntryType.Error); string badFilePath = Path.Combine(AppConfig.Inbox.FullName, m.Id + ".xml.bad"); File.WriteAllText(badFilePath, m.ToXML(true)); } } catch (Exception ex) { string badFilePath = Path.Combine(AppConfig.Inbox.FullName, m.Id + ".xml.bad"); EventLog.WriteEntry(string.Format("Exception while processing message. Message saved to \"{0}\". Exception: {1}", badFilePath, ex.ToString()), EventLogEntryType.Error); File.WriteAllText(badFilePath, m.ToXML(true)); } } if (updateJobs) { CheckJobs(); } lock (ExecuteLock) { //check for more items lock (IncomingQueueLock) { if (incoming.Count > 0) { continue; } } //check to see if we should still be running if (mainLoopRunning == false) { break; } Monitor.Wait(ExecuteLock); } } } catch (ThreadAbortException) { //eat it } catch (Exception ex) { EventLog.WriteEntry("Exception in receive loop: " + ex.ToString()); throw; } }
public void NotifyJobCompleted() { JobCompleted?.Invoke(this, EventArgs.Empty); }
public void OnJobCompleted(IJob e) { JobCompleted?.Invoke(this, e); }