【发布时间】:2011-07-26 09:13:49
【问题描述】:
我正在用 C# 为我的控制台应用程序实现超时。 我有一个名为 MySession 的类,它必须受 Session 超时的约束。这意味着在类的构造函数中,我为创建的对象配置了超时。如果在指定的超时时间内没有调用类中的任何方法,那么在后续访问任何方法时,都必须抛出 Timeout 异常。
这是该类的虚拟实现。
public class MySession {
private TimeSpan timeout;
private DateTime lastAccessedTime;
public MySession(TimeSpan timeout) {
this.timeout = timeout;
lastAccessedTime = DateTime.Now;
}
public void StoreName(string name) {
TimeSpan diff = DateTime.Now - lastAccessedTime;
if(diff.Ticks - timeout.Ticks > 0) {
throw new TimeoutException("session timed out");
}
//store logic
lastAccessedTime = DateTime.Now;
}
public void StoreAddress(string address) {
TimeSpan diff = DateTime.Now - lastAccessedTime;
if(diff.Ticks - timeout.Ticks > 0) {
throw new TimeoutException("session timed out");
}
//store logic
lastAccessedTime = DateTime.Now;
}
public void Commit() {
TimeSpan diff = DateTime.Now - lastAccessedTime;
if(diff.Ticks - timeout.Ticks > 0) {
throw new TimeoutException("session timed out");
}
//commit logic
lastAccessedTime = DateTime.Now;
}}
我有两个问题。
- 有没有更好的方法来避免在每个方法开始时进行检查?我显然可以从该代码中重构一个 IsAlive 属性,但是我仍然需要在每个方法的开头检查 IsAlive。 .NET 中是否有任何我可以继承我的类的 Session 类?
- 假设,我说会话类中的一个方法返回另一个对象。对此对象的任何调用也需要被视为从超时角度更新上次访问时间。对于多个嵌套对象,这很快就会变得非常复杂。但这只是一个假设的问题,也许是 YAGNI;但我想知道是否有任何方法可以做到这一点。
编辑:(因为原始问题中没有提到这些点)
- Session 类确实有回滚方法。我只是没有添加它以保持代码小!
- 存储实际上进入数据库事务范围内的后端数据库。因此,此类中的所有 Store 调用实际上都会将数据写入数据库,但数据库上的提交只需要在会话上的提交被调用后发生。
【问题讨论】:
-
嗯,这个类的用法好像有点奇怪。这实际上意味着您的应用程序一定会在某个时刻出现异常,因为它无法检查“会话”是否仍然存在。你实际上想要完成什么? cache with an expiration policy (.NET 4)?
-
@Groo,创建类的对象后,直到调用commit方法,如果该对象的用户在大于等于timeout的时间内没有调用该对象的任何方法,只有这样才会抛出异常。否则,不会抛出异常,最终用户将调用 Commit 并完成它。
-
真实的“用户”还是其他代码?这不应该在 UI 中实现/检查吗?
-
@Deanna,我的意思是任何其他代码 :)
-
但是 UI 中的任何活动都会重置超时。如果它只是你的代码,唯一真正的方法是检查你的代码的每个入口点。