我正在开发一个线程安全的类,我想把异步方法调用封装在同步方法调用中。也许我要找的不是"asynccall“方法的定义,而是接近它的方法。在实例上调用AsyncToStartSearchPage()时,我希望调用线程阻塞,直到新线程获得对象上的锁。这就是信号量的用武之地。asyncCalls锁用于限制使用。也许这不是最好的实现,但我觉得它需要一些方法来限制一次异步请求的数量。任何反馈都会很棒。应用程序的用途是,我有一个消费者/生产者模型,其中调用此方法的线程将开始ToStartPage()方法调用,并将其放入缓冲区。另一方面,我希望线程在ToStartPage()完成之前获取对象,并且不可能更改对象的状态。在此之前,我遇到过这样的问题:在线程的旋转能够获得锁并执行ToStartPage()之前,使用者将获得对象上的锁。
private readonly Object obj_Lock = new Object();
private readonly Object asyncCalls = new Object();
private Semaphore asyncSema = new Semaphore(0, 1);
//sync method call which has a async calling wrapper
public void ToSearchPage()
{
lock (obj_Lock)
{
//do something
}
}
//public async method wrapper
public bool AsyncToStartSearchPage()
{
//used to limit one async call.
//not crazy about this part, but I feel it needs something like this
if (Monitor.TryEnter(asyncCalls, 1))
{
try
{
Thread t = new Thread(asyncToStartPage);
t.Start();
// blocks until the new thread obtains lock on object
asyncSema.WaitOne();
}
finally
{
Monitor.Exit(asyncCalls);
}
return true;
}
else
{
return false;
}
}
private void asyncToStartPage()
{
lock (obj_Lock)
{
// now that I have aquired lock, release calling thread
asyncSema.Release();
ToSearchPage();
}
}发布于 2009-09-23 17:57:52
一个更干净的替代方案可能如下所示。您不需要信号量来让调用线程等待,直到获得锁为止。请注意我是如何使用ManualResetEvent并为此构建了冗余锁结构的。一旦外部锁被获取,事件就会被通知,因为锁是可重入的,所以内部锁将被立即获取。现在,我已经使用信号量来限制AsyncToSearchPage的执行。
public class YourThreadSafeClass
{
private Object m_Lock = new Object();
private Semaphore m_Semaphore = new Semaphore(1, 1);
public void ToSearchPage()
{
lock (m_Lock)
{
// Actual work goes here.
}
}
public bool AsyncToSearchPage()
{
// Throttle access using a semaphore
if (m_Semaphore.WaitOne(0))
{
try
{
ManualResetEvent e = new ManualResetEvent(false);
Thread t = new Thread(
() =>
{
// Acquire the lock here for the purpose of signalling the event
lock (m_Lock)
{
e.Set();
ToSearchPage(); // The lock will be acquired again here...thats ok
}
}
);
t.Start();
e.WaitOne(); // Wait for the lock to be acquired
return true;
}
finally
{
// Allow another thread to execute this method
m_semaphore.Release();
}
}
return false;
}
}请记住,这是做同样一般事情的一种稍微干净的方式。然而,我建议完全避免这种方法,因为它仍然很丑陋。我并不真正理解需要限制对异步方法的访问,也不会让它阻塞,直到包装的同步方法获得它的锁。相反,考虑在整个.NET框架中使用的BeginXXX/EndXXX异步模式。
发布于 2013-07-11 21:53:03
Spring就是最好的解决方案,它支持@Scheduled和@Async
https://stackoverflow.com/questions/1467251
复制相似问题