Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#并发字典不保存我的列表<;字符串>;页面加载之间的值_C#_Concurrentdictionary - Fatal编程技术网

C#并发字典不保存我的列表<;字符串>;页面加载之间的值

C#并发字典不保存我的列表<;字符串>;页面加载之间的值,c#,concurrentdictionary,C#,Concurrentdictionary,我已经有一段时间没有被难倒了。疯狂的是,我已经在我的代码的其他区域做过几次了,所以它几乎是完全的复制和粘贴,但除了这段代码不能正常工作之外。所以我不知何故遗漏了一些非常明显的东西 public class RoomCache { private ConcurrentDictionary<string, List<string>> _dicOnlineTraders; ILoggingService _logService = new LoggingServ

我已经有一段时间没有被难倒了。疯狂的是,我已经在我的代码的其他区域做过几次了,所以它几乎是完全的复制和粘贴,但除了这段代码不能正常工作之外。所以我不知何故遗漏了一些非常明显的东西

public class RoomCache
{
    private ConcurrentDictionary<string, List<string>> _dicOnlineTraders;
    ILoggingService _logService = new LoggingService();

    public RoomCache()
    {
        _dicOnlineTraders = new ConcurrentDictionary<string, List<string>>();
    }
    public void UpdateTraderCurrentRoom(string sRoom, string sTrader)
    {
        _dicOnlineTraders.AddOrUpdate(sRoom, new List<string>() { sTrader }, (x, y) => UpdateRoomOnlineTraderList(sTrader, y));
    }

    private List<string> UpdateRoomOnlineTraderList(string sTrader, List<string> aryTraderList)
    {
        try
        {
            if (!aryTraderList.Contains(sTrader))
            aryTraderList.Add(sTrader);

            return aryTraderList;
        }
        catch (Exception ex)
        {
            _logService.LogError(ex);
            return aryTraderList;
        }
    }
}
因此,在页面加载之间,我的字典没有保留在调用UpdateRoMonLineTraderList时添加到列表中的值。当我一步一步走过时,清单就在那里。下次我加载时 该页面已消失,我100%确信没有其他内容可以从字典中删除该值


我的字典如何不保留页面加载之间的值?关键点仍然保留,但值只是消失。我很困惑。

如果您绝对确定没有其他代码正在初始化RoomCache或从中删除预期数据,那么我最好的猜测是您有两个AppDomain在为IIS应用程序运行……因此实际上,在一个w3wp工作进程下,您有两个静态RoomCache在两个不同的AppDomain中

您可以通过在“监视”或“即时”窗口中打印:AppDomain.CurrentDomain.Id来检查这一点

如果两个页面加载实际上发生在不同的AppDomain中,则结果将是两个不同的int值

一般来说,如果ASP.NET决定为您托管两个不同的AppDomain,这将符合您的最佳利益。。。因此,如果您确实需要跨页加载可靠的信息,您可能会考虑一个进程外存储的信息。


或者,您可以使用web.config坚持ASP.NET将应用程序限制为仅一个AppDomain。但是,如果ASP.NET决定在页面加载之间回收AppDomain(这可能随时都会发生),这仍然无法保护您。

根据提供的代码,我看不到错误。然而,我有一个想法

如果列表被返回给调用者,那么调用者可能会设置为null。。。这会将集合中的列表也设置为null(因为它们当然是同一个列表)

如果存在
GetOnlineTradersWithSideEffects
,这将导致该问题

public class RoomCache
{
    private ConcurrentDictionary<string, List<string>> _dicOnlineTraders;
    ILoggingService _logService = new LoggingService();
    private static readonly object SynchronousReadLock = new object();

    // This is bad because the reference is passed out to the
    // caller and we can't be sure that callers will behave. Any
    // modifications to that list will change our list too.
    private List<string> GetOnlineTradersWithSideEffects(string sRoom)
    {
        List<string> theseTraders = null;
        _dicOnlineTraders.TryGetValue(sRoom, out theseTraders);
        return theseTraders; 
    }

    // A side-effect-free method of returning the list to a caller.
    private List<string> GetOnlineTraders(string sRoom)
    {
        List<string> theseTraders = null;
        _dicOnlineTraders.TryGetValue(sRoom, out theseTraders);
        lock (SynchronousReadLock)
        {
            // Create a new list to return to a caller, that has 
            // copies of the elements of the list in the dictionary.
            var localCopy = new List<string>(theseTraders);
            return localCopy;
        }
    }

    public RoomCache()
    {
        _dicOnlineTraders = new ConcurrentDictionary<string, List<string>>();
    }
    public void UpdateTraderCurrentRoom(string sRoom, string sTrader)
    {
        _dicOnlineTraders.AddOrUpdate(sRoom, new List<string>() { sTrader }, (x, y) => {});
    }

    private List<string> UpdateRoomOnlineTraderList(string sTrader, List<string> aryTraderList)
    {
        try
        {
            // Lock here too, when modifying the list so that our reads 
            // wait for writes and vice-versa.
            lock (SynchronousReadLock)
            {
                if (!aryTraderList.Contains(sTrader))
                    aryTraderList.Add(sTrader);
                return aryTraderList;
            }
        }
        catch (Exception ex)
        {
            _logService.LogError(ex);
            return aryTraderList;
        }
    }
}
公共类RoomCache
{
专用ConcurrentDictionary\u DiconlineRaders;
ILogingService_logService=新的LoggingService();
私有静态只读对象SynchronousReadLock=新对象();
//这是不好的,因为引用传递给了
//打电话的人,我们不能确定打电话的人是否会表现良好。有吗
//对该列表的修改也会改变我们的列表。
私有列表GetOnlineTradersWithSideEffects(字符串空间)
{
List=null;
_TryGetValue(sRoom,超出这些交易商);
交易者返回;
}
//将列表返回给调用者的一种无副作用的方法。
私有列表GetOnlineTraders(字符串空间)
{
List=null;
_TryGetValue(sRoom,超出这些交易商);
锁(SynchronousReadLock)
{
//创建一个新列表以返回给调用方,该列表具有
//字典中列表元素的副本。
var localCopy=新列表(theseTraders);
返回localCopy;
}
}
公共RoomCache()
{
_dicOnlineTraders=新的ConcurrentDictionary();
}
公共void UpdateTraderCurrentRoom(字符串空间、字符串空间)
{
_AddOrUpdate(sRoom,newlist(){sTrader},(x,y)=>{});
}
私有列表更新omonlinetraderlist(string sTrader,List aryTraderList)
{
尝试
{
//修改列表时,也在此处锁定,以便
//等待写入,反之亦然。
锁(SynchronousReadLock)
{
如果(!aryTraderList.Contains(sTrader))
aryTraderList.Add(斯特拉德);
返回aryTraderList;
}
}
捕获(例外情况除外)
{
_logService.LogError(ex);
返回aryTraderList;
}
}
}

您的意思是词典包含您以前添加的键,但现在该值为空?或者你的意思是字典元素(键和值)完全消失了吗?是的!这就是奇怪的部分。该键仍保留在字典中,而我的值(列表)已不存在。如果整个字典是空的,我会想,不知何故,对象(即使是静态的)正在重新初始化。但现在这不可能了,因为密钥仍然存在,并且值为空。它是可重复的、一致的还是间歇性的问题?它是100%可重复的。这本词典永远不适用。我有一些其他字典使用相同的类型执行相同类型的操作(这就是我复制代码的地方!)。我应该澄清一件事。该列表作为其键的值保留在字典中,但计数为0。我可以添加键,直到母牛回家,它们留下来,列表总是会被删除,并在每次页面加载时返回到0。谢谢杰夫。根据您的建议,在我的API上创建了多个AppDomain.CurrentDomain.Id。原因是-我的API在多个工作进程中运行。我已更改为1个工作进程,应用程序开始正常工作。
public class RoomCache
{
    private ConcurrentDictionary<string, List<string>> _dicOnlineTraders;
    ILoggingService _logService = new LoggingService();
    private static readonly object SynchronousReadLock = new object();

    // This is bad because the reference is passed out to the
    // caller and we can't be sure that callers will behave. Any
    // modifications to that list will change our list too.
    private List<string> GetOnlineTradersWithSideEffects(string sRoom)
    {
        List<string> theseTraders = null;
        _dicOnlineTraders.TryGetValue(sRoom, out theseTraders);
        return theseTraders; 
    }

    // A side-effect-free method of returning the list to a caller.
    private List<string> GetOnlineTraders(string sRoom)
    {
        List<string> theseTraders = null;
        _dicOnlineTraders.TryGetValue(sRoom, out theseTraders);
        lock (SynchronousReadLock)
        {
            // Create a new list to return to a caller, that has 
            // copies of the elements of the list in the dictionary.
            var localCopy = new List<string>(theseTraders);
            return localCopy;
        }
    }

    public RoomCache()
    {
        _dicOnlineTraders = new ConcurrentDictionary<string, List<string>>();
    }
    public void UpdateTraderCurrentRoom(string sRoom, string sTrader)
    {
        _dicOnlineTraders.AddOrUpdate(sRoom, new List<string>() { sTrader }, (x, y) => {});
    }

    private List<string> UpdateRoomOnlineTraderList(string sTrader, List<string> aryTraderList)
    {
        try
        {
            // Lock here too, when modifying the list so that our reads 
            // wait for writes and vice-versa.
            lock (SynchronousReadLock)
            {
                if (!aryTraderList.Contains(sTrader))
                    aryTraderList.Add(sTrader);
                return aryTraderList;
            }
        }
        catch (Exception ex)
        {
            _logService.LogError(ex);
            return aryTraderList;
        }
    }
}