【问题标题】:AutoResetEvent causes Deadlock in multithreaded UCMA 3.0 ApplicationAutoResetEvent 导致多线程 UCMA 3.0 应用程序中的死锁
【发布时间】:2012-06-06 12:04:57
【问题描述】:

在我正在调用的 Parallel.Foreach 循环中

              _helper.subscribeUserEndPoint(loop._contactGrpSvcs);

_helper 是 UserEndPoint 和所有其他操作(如订阅)的封装类

订阅方法是:

        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发出信号,呼叫无效。“有解决方法吗??

【问题讨论】:

  • 这不是死锁。当两个线程需要访问被另一个线程锁定的资源时,就会发生死锁。这不是这里的情况
  • 是什么让你认为这是一个死锁而不仅仅是一个块?要了解死锁,我们需要了解两个线程之间的交互。我认为这不会导致死锁,因为TerminateSubscribe 从不尝试获取竞争锁。
  • 对 TerminateSubscribe 的调用在哪里? BeginSubscribe 是否曾调用 TerminateSubscribe?
  • 正如 Marc 指出的那样,这很可能只是一个块,因为两个 AutoResetEvent 集从彼此靠近的两个线程转到一个线程的 WaitOne,而第二个线程仍在等待。
  • 为什么还要在这里使用等待句柄,你不能只做cntGrpSvcs.EndSubscribe(cntGrpSvcs.BeginSubscribe(null, null))吗? (加上一些异常处理/记录)

标签: c# multithreading autoresetevent ucma


【解决方案1】:

通过调用begin方法然后等待操作完成,你是在以完全同步的方式调用api。没有等待句柄更容易做到这一点。您可以将 begin 和 end 方法链接在一起。

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());
  }   
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-19
    • 1970-01-01
    • 2021-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多