Asp.net MVC API锁定一个基于方法参数的函数

本文关键字:于方法 方法 参数 函数 一个 锁定 API net Asp MVC | 更新日期: 2023-09-27 18:02:46

我有一个辅助函数来反序列化XML文件,并从中生成c#对象。

之后,对象被添加到服务器内存中。在服务器内存中添加内容的唯一方法是通过此函数。

public class DeserializeXmlHelper
{
    public void DeserializeXml(Guid xml_Id, decimal version)
    {
        // heavy process here which takes about 3 seconds
    }
}

这个函数被不同的客户端使用API方法调用(在Asp.net MVC API中创建)。

调用API时,如果其他人已经用相同的参数调用了相同的函数,我可以阻止函数的执行吗?

就像这样,但我不知道这是不是一个好的方法。

public class DeserializeXmlHelper
{
    private static readonly ConcurrentDictionary<string, object> _processes = new ConcurrentDictionary<string, object>();
    public void DeserializeXml(Guid xml_Id, decimal version)
    {
        string processKey = string.Format("{0}_v{1}", xml_Id, version.ToString("#0.0"));
        object processLocker = null;
        if (_processes.TryGetValue(processKey, out processLocker) == false)
        {
            processLocker = new object();
            _processes.TryAdd(processKey, processLocker);
        }
        lock (processLocker)
        {
            // heavy process here which takes about 3 seconds
            _processes.TryRemove(processKey);
        }
    }
}

编辑-新版本

Tim Roger的答案很成功。

但是,如果我想只在初始调用完成时返回,我可以这样做吗?(我使用ConcurrentDictionary,因为我不知道如何添加锁,但想法应该是相同的)
public class DeserializeXmlHelper
{
    private static readonly ConcurrentDictionary<string, string> _processes = new ConcurrentDictionary<string, string>();
    public void DeserializeXml(Guid xml_Id, decimal version)
    {
        string _processKey = string.Format("{0}_v{1}", xml_Id, version.ToString("#0.0"));
        string _processValue = null;
        if (_processes.TryGetValue(_processKey, out _processValue) == true)
        {
            // function already called with the same parameters
            do
            {
                System.Threading.Thread.Sleep(100);
            }
            while(_processes.TryGetValue(_processKey, out _processValue) == true)
            return;
        }
        try
        {
            _processes.TryAdd(_processKey, _processValue);
            var begin = "begin process";
            System.Threading.Thread.Sleep(10000);
            var end = "ending process";
        }
        finally
        {
            _processes.TryRemove(_processKey, out _processValue);
        }
    }
}

Asp.net MVC API锁定一个基于方法参数的函数

您的原始解决方案并不遥远,但无论当前状态如何,您似乎总是在运行该进程。

即使你已经使用了并发字典,你也需要一个锁来锁定整个字典,当你更新它的状态,因为线程可能在TryGetValueAdd之间被中断。

private static readonly ConcurrentDictionary<string, object> _processes = new ConcurrentDictionary<string, object>();
private static readonly object _dictionaryLock = new object();
public void DeserializeXml(Guid xml_Id, decimal version)
{
    string processKey = string.Format("{0}_v{1}", xml_Id, version.ToString("#0.0"));
    object processLocker = null;
    bool needsExecuting = false;
    lock (_dictionaryLock)
    {
      if (_processes.TryGetValue(processKey, out processLocker) == false)
      {
          needsExecuting = true;
          processLocker = new object();
          _processes.Add(processKey, processLocker);
      }
    }
    lock (processLocker)
    {
        if (needsExecuting)
        {
          // heavy process here which takes about 3 seconds
          _processes.Remove(processKey);
        }
    }
}