【发布时间】:2011-08-02 07:30:06
【问题描述】:
我正在使用时间戳对程序中的并发更改进行时间排序,并要求更改的每个时间戳都是唯一的。但是,我发现仅仅调用DateTime.Now 是不够的,因为如果连续调用它通常会返回相同的值。
我有一些想法,但没有什么让我觉得这是解决这个问题的“最佳”解决方案。有没有我可以编写的方法来保证每次连续调用都会产生一个唯一的DateTime?
我是否应该为此使用不同的类型,也许是 long int? DateTime 的明显优势是易于解释为实时,这与增量计数器不同。
更新:这是我最终编码为一个简单的折衷解决方案,它仍然允许我使用DateTime 作为我的临时密钥,同时确保每次调用该方法时的唯一性:
private static long _lastTime; // records the 64-bit tick value of the last time
private static object _timeLock = new object();
internal static DateTime GetCurrentTime() {
lock ( _timeLock ) { // prevent concurrent access to ensure uniqueness
DateTime result = DateTime.UtcNow;
if ( result.Ticks <= _lastTime )
result = new DateTime( _lastTime + 1 );
_lastTime = result.Ticks;
return result;
}
}
因为每个刻度值只有百万分之一秒,所以此方法仅在每秒调用 1000 万次时才会引入明显的时钟偏差(顺便说一下,它的执行效率足够高) ,这意味着我的目的完全可以接受。
这是一些测试代码:
DateTime start = DateTime.UtcNow;
DateTime prev = Kernel.GetCurrentTime();
Debug.WriteLine( "Start time : " + start.TimeOfDay );
Debug.WriteLine( "Start value: " + prev.TimeOfDay );
for ( int i = 0; i < 10000000; i++ ) {
var now = Kernel.GetCurrentTime();
Debug.Assert( now > prev ); // no failures here!
prev = now;
}
DateTime end = DateTime.UtcNow;
Debug.WriteLine( "End time: " + end.TimeOfDay );
Debug.WriteLine( "End value: " + prev.TimeOfDay );
Debug.WriteLine( "Skew: " + ( prev - end ) );
Debug.WriteLine( "GetCurrentTime test completed in: " + ( end - start ) );
...和结果:
Start time: 15:44:07.3405024
Start value: 15:44:07.3405024
End time: 15:44:07.8355307
End value: 15:44:08.3417124
Skew: 00:00:00.5061817
GetCurrentTime test completed in: 00:00:00.4950283
也就是说,在半秒内,它产生了 1000 万个唯一时间戳,而最终结果只被提前了半秒。在实际应用中,这种偏差是不明显的。
【问题讨论】:
-
应用程序是多线程的吗?这意味着两个不同的线程可以同时请求一个 ID?
-
您不能使用Guids有什么原因吗?
-
我正在使用 guid 来表示唯一身份。我在这里需要的是时间顺序......即能够查看两个更改并判断哪个先发生。向导不能这样做。理想情况下,我想使用某种形式的人类可解释的日期形式,但我认为递增的数字会在紧要关头起作用,也许与 DateTime 结合使用以提高可读性。
-
调用
new DateTime(_lastTime + 1, DateTimeKind.Utc);时指定DateTimeKind.Utc
标签: c# .net datetime concurrency