【发布时间】:2008-11-29 11:23:24
【问题描述】:
我正在编写一个服务,它有五种不同的方法,可能需要 5 秒到 5 分钟才能运行。
服务将安排这些不同的方法以不同的时间间隔运行。
我不希望任何方法同时运行,那么我如何让这些方法检查另一个方法是否正在运行并在它完成时将自身排队运行?
安东尼
【问题讨论】:
-
你用什么语言编码?
标签: c# .net multithreading
我正在编写一个服务,它有五种不同的方法,可能需要 5 秒到 5 分钟才能运行。
服务将安排这些不同的方法以不同的时间间隔运行。
我不希望任何方法同时运行,那么我如何让这些方法检查另一个方法是否正在运行并在它完成时将自身排队运行?
安东尼
【问题讨论】:
标签: c# .net multithreading
如果你想要简单,并且所有方法都在同一个类中,你可以使用[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] 定义特定模式,甚至包括私有锁的示例,作为“有效”。但是,MS 规范坚持使用 this/typeof。
【讨论】:
有MethodImplOptions.Synchronized attribute,如在 文章Synchronized method access in C#,但这可能会导致死锁,如 MSDN 所述。听起来,就您的使用而言,这不是一个大问题。
否则,最简单的方法是使用lock statement 来确保一次只执行一个方法:
class ServiceClass
{
private object thisLock = new object();
public Method1()
{
lock ( thisLock )
{
...
}
}
public Method2()
{
lock ( thisLock )
{
...
}
}
...
}
【讨论】:
如果你使用java,你可以创建synchronized方法,这样可以防止多个线程同时访问它。
【讨论】:
一般来说,我强烈反对使用 MethodImpl(MethodImplOptions.Synchronized) 属性来进行线程同步。如果您要进行多线程编程,您真的应该非常仔细地考虑您应该锁定的确切位置和方式。
我可能有点夸张,但我发现 MethodImpl 同步方法和其他方法之间有太多相似之处,例如在 VB 中使用 End 语句。它经常向我发出信号,表明您并不真正知道自己在做什么,并希望此语句/方法/属性能神奇地解决您的问题。
【讨论】: