C# 多线程逻辑问题

C# 多线程逻辑问题,c#,multithreading,network-programming,C#,Multithreading,Network Programming,我有一个类,它在浏览器和Web服务器之间执行缓存,并充当代理服务器。我只给出了简单的类定义 在这门课上,我有三种方法 RequestNewCacheFilePath返回用于将网络文件保存到磁盘的唯一id(每次函数调用后递增1) CommitNewCacheFilePath在文件下载后将唯一id提交到字典中。直到将其id 0下载到字典中 在RequestNewCacheFilePath函数中,添加了一个值为0的字典项。这意味着正在为该资源下载资源。当文件下载完成时,字典将使用其实际唯一的缓存id进

我有一个类,它在浏览器和Web服务器之间执行缓存,并充当代理服务器。我只给出了简单的类定义

在这门课上,我有三种方法

  • RequestNewCacheFilePath返回用于将网络文件保存到磁盘的唯一id(每次函数调用后递增1)

  • CommitNewCacheFilePath在文件下载后将唯一id提交到字典中。直到将其id 0下载到字典中

  • 在RequestNewCacheFilePath函数中,添加了一个值为0的字典项。这意味着正在为该资源下载资源。当文件下载完成时,字典将使用其实际唯一的缓存id进行更新。但在多线程场景中,CommitNewCacheFilePath函数调试断言有时会失败

    public class CacheManager
    {
        const string INDEX_FILE_NAME = "index.txt";
    
        Dictionary<string, int> _dictResources = new Dictionary<string, int>();
    
        public IAppServer Server { get; private set; }
    
        object _syncCacheIdObject = new object();
        int _cacheId;
    
        public string CacheDirectoryPath { get; private set; }
    
        public CacheManager(IAppServer server)
        {
            server.ThrowIfNull("server");
    
            Server = server;
    
            CacheDirectoryPath = (server.Config as ProxyServerConfig).CacheDirectoryPath;
            if (CacheDirectoryPath.IsEmpty())
                CacheDirectoryPath = Path.Combine("C:\\", Application.ProductName);
    
            if (!Directory.Exists(CacheDirectoryPath))
                Directory.CreateDirectory(CacheDirectoryPath);
    
        }
    
        public int GetCacheId(string key)
        {
            int value;
            if (_dictResources.TryGetValue(key, out value))
                return value;
            else
                return -1;
        }
    
        public string RequestNewCacheFilePath(string key)
        {
            int cacheId;
    
            lock (_syncCacheIdObject)
            {
                cacheId = ++_cacheId;
            }
    
            lock (_dictResources)
            {
                if (_dictResources.ContainsKey(key))
                    return null;
                else
                {
                    _dictResources[key] = 0;
                    return Path.Combine(CacheDirectoryPath, cacheId + ".cache");
                }
            }
        }
    
        public void CommitNewCacheFilePath(string key, string cachedFilePath)
        {
            int cachedId = int.Parse(Path.GetFileNameWithoutExtension(cachedFilePath));
    
            lock (_dictResources)
            {
                Debug.Assert(_dictResources[key] == 0);
    
                _dictResources[key] = cachedId;
            }
        }
    
        public void RevertNewCacheFilePath(string resourcePath)
        {
            lock (_dictResources)
            {
                _dictResources.Remove(resourcePath);
            }
        }
    }
    
    公共类缓存管理器
    {
    常量字符串索引\u文件\u NAME=“INDEX.txt”;
    字典_dictResources=新字典();
    公共IAppServer服务器{get;private set;}
    对象_syncCacheIdObject=新对象();
    int_cacheId;
    公共字符串CacheDirectoryPath{get;private set;}
    公共缓存管理器(IAppServer服务器)
    {
    server.ThrowIfNull(“服务器”);
    服务器=服务器;
    CacheDirectoryPath=(server.Config作为ProxyServerConfig);
    if(CacheDirectoryPath.IsEmpty())
    CacheDirectoryPath=Path.Combine(“C:\\”,Application.ProductName);
    如果(!Directory.Exists(CacheDirectoryPath))
    CreateDirectory(CacheDirectoryPath);
    }
    public int GetCacheId(字符串键)
    {
    int值;
    if(_dictResources.TryGetValue(key,out value))
    返回值;
    其他的
    返回-1;
    }
    公共字符串请求NewCacheFilePath(字符串键)
    {
    int cacheId;
    锁定(_syncCacheIdObject)
    {
    cacheId=++\u cacheId;
    }
    锁定(资源)
    {
    if(_dictResources.ContainsKey(键))
    返回null;
    其他的
    {
    _数字资源[键]=0;
    返回Path.Combine(CacheDirectoryPath,cacheId+“.cache”);
    }
    }
    }
    public void CommitNewCacheFilePath(字符串键、字符串cachedFilePath)
    {
    int cachedId=int.Parse(Path.GetFileNameWithoutExtension(cachedFilePath));
    锁定(资源)
    {
    Assert(_dictResources[key]==0);
    _dictResources[key]=cachedId;
    }
    }
    公共无效RevertNewCacheFilePath(字符串resourcePath)
    {
    锁定(资源)
    {
    _删除(resourcePath);
    }
    }
    }
    
    调用RequestNewCacheFilePath的代码看起来像什么?是什么用特定的键触发了对该方法的调用?允许RequestNewCacheFilePath()返回null是一种强烈的代码味道,必须隐藏并发错误。添加跟踪以调试此项。@是的,我在其他代码中发现了错误。实际上,针对不同的资源多次调用CommitNewCacheFilePath。就这样发生了。谢谢