C# 为什么我在进程的运行持续时间内得到了不正确的值?
基本上,我希望计时不是由代码触发的外部进程的运行持续时间。为了实现这一点,我使用以下代码(基于此)按流程名称订阅特定流程开始和结束的事件:C# 为什么我在进程的运行持续时间内得到了不正确的值?,c#,validation,process,filtering,C#,Validation,Process,Filtering,基本上,我希望计时不是由代码触发的外部进程的运行持续时间。为了实现这一点,我使用以下代码(基于此)按流程名称订阅特定流程开始和结束的事件: addRuntimeData(双秒)方法定义为: public void addRuntimeData(double seconds) { this.runDurations.Add(seconds); if (this.runDurations.Count > Properties.Settings.Default.MaxRunDur
addRuntimeData(双秒)
方法定义为:
public void addRuntimeData(double seconds)
{
this.runDurations.Add(seconds);
if (this.runDurations.Count > Properties.Settings.Default.MaxRunDurationData)
this.runDurations.RemoveAt(0);
this.updateLog();
}
public void updateLog()
{
this.logfileDirectory = Properties.Settings.Default.LogfileDirectory;
this.logfileFullPath = logfileDirectory + this.task.Name.toValidFilename() + this.logfileExtension;
Directory.CreateDirectory(logfileDirectory); // create directory if it does not already exist
this.toXElement().Save(this.logfileFullPath); // generate the XML and write it to the log file
}
现在,我正在尝试对我编写的测试进程计时,而测试进程所做的只是对Console.WriteLine(“测试进程”)的一次调用代码>,因此记录的持续时间的适当值应大致在0-2秒范围内
有时,我得到的值是适当的,有时我得到的值实际上不可能被记录下来,例如63619141321.2978秒。这大约相当于2017.3年,这让我认为这可能与记录为01/01/0001 00:00:01
或类似内容的开始时间有关;这个问题可能与此有关吗
如果这是一个我无能为力的问题(例如,如果它与操作系统触发消息的方式/时间有关),有没有办法过滤掉这些明显无效的数据点?关于01/01/0001 00:00:01
,你基本上是对的
创建DateTime对象将在凌晨1/1/0001 12:00:00开始。您评论说,processStart
声明时没有初始化,这意味着它的默认开始时间为1/1/0001 12:00:00 AM。我猜ProcessEnd是在ProcessStart被触发之前被触发的
下面的代码生成与您描述的类似的结果,并使用声明后未更改的DateTime
private static DateTime date;
public static void Main(string[] args) {
const double largeVal = 63619141321;
Console.WriteLine(date.ToString());
double totalSeconds = (DateTime.Now - date).TotalSeconds;
Console.WriteLine(totalSeconds - largeVal);
Console.WriteLine("Press any key to continue . . . ");
Console.ReadKey(true);
}
关于01/01/0001 00:00:01
,您基本上是对的
创建DateTime对象将在凌晨1/1/0001 12:00:00开始。您评论说,processStart
声明时没有初始化,这意味着它的默认开始时间为1/1/0001 12:00:00 AM。我猜ProcessEnd是在ProcessStart被触发之前被触发的
下面的代码生成与您描述的类似的结果,并使用声明后未更改的DateTime
private static DateTime date;
public static void Main(string[] args) {
const double largeVal = 63619141321;
Console.WriteLine(date.ToString());
double totalSeconds = (DateTime.Now - date).TotalSeconds;
Console.WriteLine(totalSeconds - largeVal);
Console.WriteLine("Press any key to continue . . . ");
Console.ReadKey(true);
}
根本问题是ManagementEventWatcher从根本上说是一种轮询机制,对于一个非常短的流程,结束事件可能在开始事件之前被拾取。如果启动时间从未初始化过(默认值为1/1/0001),那么您将看到您所描述的内容。实际上,这可能不是一个现实的用例,但正如您所观察到的,它是可能发生的。我认为解决这个问题的最好方法是不记录流程开始事件的开始时间
在计算总运行时间时,您实际上不需要查看process started事件。您可以从end事件中获取Win32_进程实例,并使用CreationDate计算进程的总运行时间。我注意到终止日期还没有确定。在这种情况下,我只使用触发结束事件的当前时间:
private static void ProcessEnded(object sender, EventArrivedEventArgs e)
{
Console.WriteLine($"Process ended event at: {DateTime.Now}");
var targetProcess = e.NewEvent.Properties["TargetInstance"].Value as ManagementBaseObject;
if (targetProcess != null)
{
Console.WriteLine("Properties:");
foreach (PropertyData data in targetProcess.Properties)
{
Console.WriteLine($"{data.Name} = {data.Value}");
}
DateTime creationDate = GetDateTimeOrDefault(targetProcess.Properties["CreationDate"], DateTime.Now);
DateTime terminationDate = GetDateTimeOrDefault(targetProcess.Properties["TerminationDate"], DateTime.Now);
var totalRunTime = (terminationDate - creationDate).TotalSeconds;
Console.WriteLine($"Creation: {creationDate}, Termination: {terminationDate}, Elapsed: {totalRunTime}");
// this.logger.addRuntimeData(totalRunTime);
}
else
{
Console.WriteLine("Could not get target process");
}
}
private static DateTime GetDateTimeOrDefault(PropertyData managementDateProperty, DateTime defaultValue)
{
string dateString = managementDateProperty.Value as string;
if (!string.IsNullOrEmpty(dateString))
{
return ManagementDateTimeConverter.ToDateTime(dateString);
}
else
{
return defaultValue;
}
}
根本问题是ManagementEventWatcher从根本上说是一种轮询机制,对于一个非常短的流程,结束事件可能在开始事件之前被拾取。如果启动时间从未初始化过(默认值为1/1/0001),那么您将看到您所描述的内容。实际上,这可能不是一个现实的用例,但正如您所观察到的,它是可能发生的。我认为解决这个问题的最好方法是不记录流程开始事件的开始时间
在计算总运行时间时,您实际上不需要查看process started事件。您可以从end事件中获取Win32_进程实例,并使用CreationDate计算进程的总运行时间。我注意到终止日期还没有确定。在这种情况下,我只使用触发结束事件的当前时间:
private static void ProcessEnded(object sender, EventArrivedEventArgs e)
{
Console.WriteLine($"Process ended event at: {DateTime.Now}");
var targetProcess = e.NewEvent.Properties["TargetInstance"].Value as ManagementBaseObject;
if (targetProcess != null)
{
Console.WriteLine("Properties:");
foreach (PropertyData data in targetProcess.Properties)
{
Console.WriteLine($"{data.Name} = {data.Value}");
}
DateTime creationDate = GetDateTimeOrDefault(targetProcess.Properties["CreationDate"], DateTime.Now);
DateTime terminationDate = GetDateTimeOrDefault(targetProcess.Properties["TerminationDate"], DateTime.Now);
var totalRunTime = (terminationDate - creationDate).TotalSeconds;
Console.WriteLine($"Creation: {creationDate}, Termination: {terminationDate}, Elapsed: {totalRunTime}");
// this.logger.addRuntimeData(totalRunTime);
}
else
{
Console.WriteLine("Could not get target process");
}
}
private static DateTime GetDateTimeOrDefault(PropertyData managementDateProperty, DateTime defaultValue)
{
string dateString = managementDateProperty.Value as string;
if (!string.IsNullOrEmpty(dateString))
{
return ManagementDateTimeConverter.ToDateTime(dateString);
}
else
{
return defaultValue;
}
}
可能会告诉您。@MattRowland lol rekt可能是因为在启动processStart
并初始化processStart
之前记录了一个持续时间。在这里,结束事件很可能在开始事件之前发生。观察者只是在投票。“WITHIN 1”子句的目的是设置轮询间隔。有时,最终进程观察者设法首先捕获其事件。如果开始时间没有初始化,那么它会给你你看到的。@mikez因此会在ProcessEndWatcher
中将内1
更改为内2
,解决这个问题,因为ProcessStartWatcher
被设置为内1
,这将确保结束事件不会在开始事件之前触发?可能会告诉您。@MattRowland lol rekt可能是因为在启动processStart
并初始化processStart
之前记录了一个持续时间。在这里,结束事件很可能在开始事件之前发生。观察者只是在投票。“WITHIN 1”子句的目的是设置轮询间隔。有时,最终进程观察者设法首先捕获其事件。如果开始时间没有初始化,那么它会给你你看到的。@mikez因此会在ProcessEndWatcher
中将内1
更改为内2
,解决这个问题,因为ProcessStartWatcher
被设置为内1
,这将确保结束事件不会在开始事件之前触发?但我将processStart
初始化为DateTime。现在
,而不是new DateTime()
?@mjones.udri您能对定义processStart的行进行注释吗?它是一个类级变量<代码>私有日期时间进程开始代码>,然后直到进程启动
事件处理程序触发才初始化this.processStart=DateTime.Now代码>@mjones.udri,当您声明