我正在编写一个服务,它有五种不同的方法,这些方法的运行时间在5秒到5分钟之间。
这项服务将安排不同的方法在不同的时间间隔内运行。
我不想让任何方法并发运行,那么我该如何让这些方法检查是否有其他方法正在运行,然后在其完成后排队运行?
安东尼
我正在编写一个服务,它有五种不同的方法,这些方法的运行时间在5秒到5分钟之间。
这项服务将安排不同的方法在不同的时间间隔内运行。
我不想让任何方法并发运行,那么我该如何让这些方法检查是否有其他方法正在运行,然后在其完成后排队运行?
安东尼
如果你想要“简单”,并且所有的方法都在同一个类中,你可以只使用[MethodImpl]
:
[MethodImpl(MethodImplOptions.Synchronized)]
public void Foo() {...}
[MethodImpl(MethodImplOptions.Synchronized)]
public void Bar() {...}
例如对于实例方法,这个锁定在 this
上;对于静态方法,这个锁定在 typeof(TheClass)
上。
因此,这些锁对象是公开的 - 所以有一个远程(但真实的)机会,另一个代码段可能会锁定它们。通常认为最好的实践是创建自己的锁对象:
private readonly object syncLock = new object(); // or static if needed
...
public void Foo() {
lock(syncLock) {
...
}
}
等等
附带说明一个有趣的事实;ECMA规范没有为[MethodImpl]定义特定的模式,甚至包括一个私有锁的示例也被认为是“有效”的。然而,微软规范坚持要求采用这种/typeof形式。
There s the MethodImplOptions.Synchronized attribute, as noted in the article Synchronized method access in C#, but that can lead to deadlocks as noted at MSDN. It sounds like, for your usage, this won t be a big concern.
否则,最简单的方法是使用lock语句确保只有一个方法在同一时间执行:
class ServiceClass
{
private object thisLock = new object();
public Method1()
{
lock ( thisLock )
{
...
}
}
public Method2()
{
lock ( thisLock )
{
...
}
}
...
}
如果你正在使用Java,你可以使方法同步,这将防止多个线程同时访问。
总的来说,我强烈不建议使用MethodImpl(MethodImplOptions.Synchronized)属性来进行线程同步。如果你要进行多线程编程,你真的应该非常仔细地考虑在哪里和如何进行锁定。
我可能有点夸张,但是我发现MethodImpl同步方法与其他方法(如在VB中使用End语句)存在太多相似之处。这经常向我传达一种信息,即您并不真正知道自己在做什么,并希望这种语句/方法/属性可以神奇地解决您的问题。