C# windows窗体应用程序的并发用户

C# windows窗体应用程序的并发用户,c#,winforms,concurrency,C#,Winforms,Concurrency,我正在开发一个基于客户机-服务器的应用程序。我想限制 登录到我的应用程序的用户数。 我的第一种方法是创建一个表(称之为“X”)来存储用户名、机器名和IP。。 成功登录到应用程序的每个用户的。 每次登录时,我都会检查表“X”中的行数是否等于限制 然后我提醒用户,如果没有,我将向表“X”添加一条新记录,存储 当前行作为静态对象中的对象。 当用户注销时,我将删除与保存的静态对象关联的记录。 我正在调用删除formclosing事件中记录的函数,该函数工作正常,但唯一的问题是,如果我按下“结束任务”或“

我正在开发一个基于客户机-服务器的应用程序。我想限制 登录到我的应用程序的用户数。 我的第一种方法是创建一个表(称之为“X”)来存储用户名、机器名和IP。。 成功登录到应用程序的每个用户的。 每次登录时,我都会检查表“X”中的行数是否等于限制 然后我提醒用户,如果没有,我将向表“X”添加一条新记录,存储 当前行作为静态对象中的对象。 当用户注销时,我将删除与保存的静态对象关联的记录。 我正在调用删除formclosing事件中记录的函数,该函数工作正常,但唯一的问题是,如果我按下“结束任务”或“结束进程”或任何其他异常操作,记录将保留在表中。
在这种情况下,你建议怎么办

最好的方法是创建到服务器的长寿命tcp连接,并检测它何时关闭——从应用程序终止到网络故障,任何原因都会发生这种情况


如果您的服务器技术不允许创建这种连接。您应该定期将“我还活着”数据包从客户端发送到服务器。如果超过某个超时时间,则将该客户端标记为已断开连接。

我遇到了类似的难题,我决定将所有内容永远保留在缓存/DB中。 我的解决方案是限制缓存大小。。。(您可以在下面找到我的代码)

公共类CacheWithSizeLimit
{
私有int_缓存大小;
公共CacheWithSizeLimit(int cacheSize=10000)
{
缓存=新的ConcurrentDictionary();
_cacheSize=cacheSize;
}
私有ConcurrentDictionary缓存{get;set;}
公共TValue GetCachedValue(TKey inputKey)
{
键值对结果;
var key=inputKey.GetHashCode()%\u cacheSize;
Cache.TryGetValue(键,输出结果);
如果(!IsNullOrEmpty(result.Key)和&result.Key.Equals(inputKey))
{
返回结果值;
}
返回默认值(TValue);
}
私有布尔值为NullOrEmpty(T值)
{
返回EqualityComparer.Default.Equals(值,默认值(T));
}
public void SetCachedValue(TKey inputKey,TValue inputValue)
{
var key=inputKey.GetHashCode()%\u cacheSize;
AddOrUpdate(key,newkeyValuePair(inputKey,inputValue));
}
内部空隙清除()
{
缓存=新的ConcurrentDictionary();
}
}

如果这种方法对您不起作用,那么您可以依赖实际的连接断开事件或超时。

谢谢大家的建议。在与客户进一步讨论该问题后 在团队中,我决定在用户登录时运行一个小小的后台应用程序
正确的参数和此应用程序将为我完成所有检查。

我想最常见的方法是让会话在一段时间的沉默后超时。这意味着您的应用程序将需要定期发送保持活动状态的消息。您还可以在后台线程中发送活动状态信号,并根据活动连接的数量进行决定。
public class CacheWithSizeLimit<TKey,TValue>
{
    private int _cacheSize;

    public CacheWithSizeLimit(int cacheSize = 10000)
    {
        Cache = new ConcurrentDictionary<int, KeyValuePair<TKey, TValue>>();
        _cacheSize = cacheSize;
    }

    private ConcurrentDictionary<int, KeyValuePair<TKey, TValue>> Cache { get; set; }

    public TValue GetCachedValue(TKey inputKey)
    {
        KeyValuePair<TKey,TValue> result;
        var key = inputKey.GetHashCode() % _cacheSize;

        Cache.TryGetValue(key, out result);

        if (!IsNullOrEmpty(result.Key) && result.Key.Equals(inputKey))
        {
            return result.Value;
        }
        return default(TValue);
    }

    private bool IsNullOrEmpty<T>(T value)
    {
        return EqualityComparer<T>.Default.Equals(value, default(T));
    }

    public void SetCachedValue(TKey inputKey, TValue inputValue)
    {
        var key = inputKey.GetHashCode() % _cacheSize;
        Cache.AddOrUpdate(key, new KeyValuePair<TKey, TValue>(inputKey, inputValue));
    }

    internal void Clear()
    {
            Cache = new ConcurrentDictionary<int, KeyValuePair<TKey, TValue>>();
    }
}