首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步方法调用调用同步方法调用

异步方法调用调用同步方法调用
EN

Stack Overflow用户
提问于 2009-09-23 16:44:46
回答 2查看 2.3K关注 0票数 1

我正在开发一个线程安全的类,我想把异步方法调用封装在同步方法调用中。也许我要找的不是"asynccall“方法的定义,而是接近它的方法。在实例上调用AsyncToStartSearchPage()时,我希望调用线程阻塞,直到新线程获得对象上的锁。这就是信号量的用武之地。asyncCalls锁用于限制使用。也许这不是最好的实现,但我觉得它需要一些方法来限制一次异步请求的数量。任何反馈都会很棒。应用程序的用途是,我有一个消费者/生产者模型,其中调用此方法的线程将开始ToStartPage()方法调用,并将其放入缓冲区。另一方面,我希望线程在ToStartPage()完成之前获取对象,并且不可能更改对象的状态。在此之前,我遇到过这样的问题:在线程的旋转能够获得锁并执行ToStartPage()之前,使用者将获得对象上的锁。

代码语言:javascript
复制
    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();
        }
    }
EN

回答 2

Stack Overflow用户

发布于 2009-09-23 17:57:52

一个更干净的替代方案可能如下所示。您不需要信号量来让调用线程等待,直到获得锁为止。请注意我是如何使用ManualResetEvent并为此构建了冗余锁结构的。一旦外部锁被获取,事件就会被通知,因为锁是可重入的,所以内部锁将被立即获取。现在,我已经使用信号量来限制AsyncToSearchPage的执行。

代码语言:javascript
复制
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异步模式。

票数 2
EN

Stack Overflow用户

发布于 2013-07-11 21:53:03

Spring就是最好的解决方案,它支持@Scheduled和@Async

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1467251

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档