AutoResetEvent导致多线程UCMA 3.0应用程序中的死锁

时间:2012-06-06 12:04:58

标签: c# multithreading autoresetevent ucma

在My Parallel.Foreach循环中,我正在调用

              _helper.subscribeUserEndPoint(loop._contactGrpSvcs);

_helper是UserEndPoint的Encapsulating类以及Subscribes等所有其他操作

订阅方法是:

        public void subscribeUserEndPoint(ContactGroupServices cntGrpSvcs)
        {

            cntGrpSvcs.BeginSubscribe(TerminateSubscribe, cntGrpSvcs);

            _contactSubscribeCompleted.WaitOne();

            LOG.Info("Returning from Successful Subscribe Endpoint");
        }


    private void TerminateSubscribe(IAsyncResult result)
    {

        ContactGroupServices cntGrpSvcs = result.AsyncState as ContactGroupServices;
        try
        {
            cntGrpSvcs.EndSubscribe(result);
        }
        catch (Exception ex)
        {
            LOG.Error("Failed to Complete Subscribe. " + ex.StackTrace);
        }
        CollaborationSubscriptionState state = cntGrpSvcs.CurrentState;
        LOG.Info("Subscribed State = " + state.ToString());

            _contactSubscribeCompleted.Set();

    }

在等待_contactSubscribeCompleted.WaitOne()时线程死锁;有什么方法可以避免这种死锁争用?

干杯,

  -- Brian
PS:死锁可能发生的一个原因是由于AutoResetEvent的固有问题 - 来自文档 - “无法保证每次调用Set方法都会释放一个线程。如果两个调用也是如此一起关闭,以便第二次调用在线程释放之前发生,只释放一个线程。就好像第二次调用没有发生一样。另外,如果在没有线程等待且AutoResetEvent已经调用时调用了Set发出信号,电话没有效果。“这有解决方法吗?

1 个答案:

答案 0 :(得分:0)

通过调用begin方法然后等待操作完成,您将以完全同步的方式调用api。没有等待处理,这样做会更容易。您可以将开始和结束方法链接在一起。

public void subscribeUserEndPoint(ContactGroupServices cntGrpSvcs)
{
  try
  {
    cntGrpSvcs.EndSubscribe(cntGrpSvcs.BeginSubscribe(null, null));
    CollaborationSubscriptionState state = cntGrpSvcs.CurrentState;
    LOG.Info("Subscribed State = " + state.ToString());
    LOG.Info("Returning from Successful Subscribe Endpoint");
  }
  catch (Exception ex)
  {
    LOG.Error("Failed to Complete Subscribe. Exception: " + ex.ToString());
  }   
}