c# web服务中超时的锁

本文关键字:超时 中超 web 服务 | 更新日期: 2023-09-27 18:02:05

我的web服务有以下代码

lock(typeof MyWebServiceClass)

我调用第三方不可更改代码,它永远不会返回。繁荣!砰!

我现在永远被锁定了,我的网站崩溃了。

这个永远不会返回,只在很长一段时间内发生一次。

是否可以创建一个超时的锁?IE锁码5分钟后再解锁?

c# web服务中超时的锁

与其创建定时锁,不如将第三方请求放在单独的线程/任务中。然后,启动线程(如果. net 4.0和TPL可用,则启动任务),并超时加入响应。如果连接超时,则取消线程(或调用TPL任务上的cancel令牌)。

是否可以创建一个超时的锁?

是的,这种不愉快的情况通常被称为死锁。

通常,锁定静态私有对象而不是锁定实例字段或类本身是一种好做法:

private static object _syncRoot = new object();

然后:

lock(_syncRoot) {
}

如果第三方API有取消机制,那么就使用它。

lock(typeof MyWebServiceClass)
{
  if (ThirdPartyApiThatAcceptsTimeout(TimeSpan.FromMinutes(5)))
  {
    // The call was successful so proceed.
  }
  else
  {
    // The call timed out so bail out.
    return;
  }
}

然而,我高度怀疑这个API没有取消机制,所以这就是你提出这个问题的原因。如果是这样的话,那么这就变得更加困难了。

幼稚的方法是将API调用推迟到另一个线程。如果线程没有及时响应,那么你可以中止它。
lock(typeof MyWebServiceClass)
{
  var thread = new Thread(
    () =>
    {
      ThirdPartyApiThatCouldBlockIndefinitely();
    });
  thread.Start();
  if (thread.Join(TimeSpan.FromMinutes(5))
  {
    // The call was successful so proceed.
  }
  else
  {
    // The call timed out so bail out.
    thread.Abort();
    return;
  }
}

这有很多问题。首先,不能保证线程会接受中止请求。自2.0以来,CLR中有特殊的规则来规定何时可以将中止注入线程。我相信CLR会在执行非托管代码时延迟注入。因此,如果你的API是非托管的,那么中止可能无法工作。此外,中止是自愿的,因为线程可以捕获ThreadAbortException并忽略它。其次,中止是危险的,因为中止可以被异步注入。这使得防止损坏共享状态变得非常困难。这就是AppDomain通常在abort后终止的原因。

处理这个问题最安全的方法是将API调用放到一个单独的进程中。你将不得不使用进程间通信协议,如。net Remoting、WCF、管道等来将数据传输到调用中,这将是一个真正的痛苦维护。但是,这将是最安全的,因为您可以安全地终止进程,而不会有损坏调用者的AppDomain的风险。

我很同情你,因为这个问题很难正确解决。