背景

  在Web中Session的功能很好用,于是想Winform中实现该功能,典型应用场景则是登陆成功后,当一段时间不操作,则该会话过期,提示重新登陆。

资源下载

  测试代码

  示例说明:登陆进去10s不操作或者访问Cache后10秒不操作,则会提示登陆超时

实现

  1. 设计CacheContainer类,使用Dictionary存放变量,并添加互斥锁SyncRoot,避免多线程操作带来异常。

  2. CacheContainer内部的变量,如果持续10秒(测试使用的默认值)没有访问或操作,则自动移除该变量,并触发回调。

  3. 当程序访问CacheContainer内部的变量,过期时间从当前时间开始计时。

  4. 变量第一次计时在加入CacheContainer时。

  具体代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading; namespace WindowsFormsApplication1
{
public sealed class CacheContainer
{
//互斥锁
private object SyncRoot = new object();
//对象字典
private Dictionary<string, CacheObj> dic = new Dictionary<string, CacheObj>(); internal class CacheObj : IDisposable
{
//公有变量
public object Value { get; set; }
public int Expired { get; set; }
public WaitCallback callback { get; set; }
public AutoResetEvent ar = new AutoResetEvent(false);
public TimeSpan Timeout
{
get
{
return TimeSpan.FromSeconds(Expired);
}
}
public CacheObj(object value, int expired = )
{
Value = value;
Expired = expired;
callback = new WaitCallback((obj) =>
{
Console.WriteLine("{0}:已过期,过期时间:{1}", obj, DateTime.Now);
});
} public void Dispose()
{
GC.SuppressFinalize(this);
} ~CacheObj()
{
Dispose();
}
} private static CacheContainer container = new CacheContainer();
private CacheContainer() { }
public static CacheContainer GetInstance() { return container; } public object this[string key]
{
get
{
//访问变量成功,则时间重新计时
CacheObj cache;
lock (SyncRoot)
{
if (dic.TryGetValue(key, out cache))
{
cache.ar.Set();
return cache.Value;
}
}
return null;
}
set
{
//通过属性添加参数,有则覆盖,无则添加,操作完毕重新计时
CacheObj cache;
lock (SyncRoot)
{
if (dic.TryGetValue(key, out cache))
{
cache.Value = value;
cache.ar.Set();
}
else
Add(key, value);
}
}
} public void Add(string key, object value)
{
lock (SyncRoot)
dic.Add(key, new CacheObj(value));
AutoCheck(key);
} public void Add(string key, object value, int expired)
{
lock (SyncRoot)
dic.Add(key, new CacheObj(value, expired));
AutoCheck(key);
} public void Add(string key, object value, int expired, WaitCallback callback)
{
lock (SyncRoot)
dic.Add(key, new CacheObj(value, expired) { callback = callback });
AutoCheck(key);
} private void AutoCheck(string key)
{
//开启一个子线程去控制变量的过期
ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
{
CacheObj tmpCache;
while (true)
{
//从字典中取出对象
lock (SyncRoot)
tmpCache = dic[key];
//打印变量过期时间
Console.WriteLine("{0} 等待销毁变量 时间为:{1}秒", DateTime.Now, tmpCache.Expired);
//记录开始时间
var timeStart = DateTime.Now;
//中断,超时时间一到,自动向下执行
tmpCache.ar.WaitOne(TimeSpan.FromSeconds(tmpCache.Expired));
//检查时间是否已经达到超时时间,超时则移除该信息,并触发回调
if ((DateTime.Now - timeStart) >= tmpCache.Timeout)
{
lock (SyncRoot)
dic.Remove(key);
if (tmpCache.callback != null) tmpCache.callback(tmpCache.Value);
break;
}
}
}));
} public void Remove(string key)
{
lock (SyncRoot)
{
CacheObj cache;
if (dic.TryGetValue(key, out cache))
{
cache.Expired = ;
cache.ar.Set();
}
}
}
}
}

问题  

  CacheContainer中的变量,均是在线程池里有个线程去检测它,也就是说有10个变量,线程池里就会多10个子线程,这样会不会不太好。

  该方法仅是抛砖引玉,不知道在Winform中实现缓存变量xx分钟这样的功能有没有更好的方法,欢迎赐教,谢谢!

Winform 模拟Session的更多相关文章

  1. Winform模拟post请求和get请求登录网站

    引言 最近有朋友问如何用winform模拟post请求,然后登录网站,稍微想了一下,大致就是对http报文的相关信息的封装,然后请求网站登录地址的样子.发现自己的博客中对这部分只是也没总结,就借着这股 ...

  2. Memcache+cookie实现模拟session

    上一片讲到Memcached在Windows上的安装,和用Telnet工具进行命令操作,在稍微了解了原理之后,我也就开始尝试着用程序来对Memcached进行操作.这一篇分为两个部分,第一部分是用.n ...

  3. Python day15装饰器基本理论,以及结合全局变量模拟session

    装饰器(decorator):为其他函数添加附加功能 原则:1.不修改被修饰函数源代码 2.不修改被修饰函数的调用方式 装饰器=高阶函数+函数嵌套+闭包 import time def timmer( ...

  4. 利用Node.js实现模拟Session验证的登陆

    1.身份验证和用户登陆 在一般的Web应用上,假设要实现用户登陆,最经常使用,也是最简单的方法就是使用Session,主要的思路是在Session中保留一些用户身份信息,然后每次在Session中取, ...

  5. 通过winform+模拟登录实现快速一键登录到人才招聘网站

    之前为了便于人事部门招聘登录网站更简洁高效,免去每天频繁输网址.用户名.密码等相关登录信息,特基于winform+HttpWebRequest实现模拟请求登录,最终达到一键登录到招聘网站后台的效果. ...

  6. sonar + jacoco + mockMvc 模拟session 用户登录 配合SpringSecurity 权限 快速测试代码覆盖率.

    遇到mock 测试简直就是神器,特别是要做代码覆盖率,直接测试controller就好了,缺点,虽然可以回滚事务,但是依赖数据库数据,解决,根据SpringBoot ,再建立一个专门跑单元测试的数据库 ...

  7. python---cookie模拟登陆和模拟session原理

    cookie模拟登陆: import tornado.web class IndexHandler(tornado.web.RequestHandler): def get(self): #self. ...

  8. winform实现Session功能(保存用户信息)

    问题描述:在winform中想实现像BS中类似Session的功能,放上需要的信息,在程序中都可以访问到. 解决方案:由于自己很长时间没有做过winform的程序,一时间竟然手足无措起来.后来发现wi ...

  9. C# winform 模拟键盘鼠标操作

    1.获取鼠标位置 private void timer1_Tick(object sender, EventArgs e) { // timer1.Stop(); // int x = Control ...

随机推荐

  1. java练习题——字符串

    一.动手动脑之String.equals()方法: 判断s1和s2的内容相同s1.equals(s2). 判断s1和s2的地址相同s1 == s2. 二.整理String类的Length().char ...

  2. django中间件CsrfViewMiddleware源码分析,探究csrf实现

    Django Documentation csrf保护基于以下: 1. 一个CSRF cookie 基于一个随机生成的值,其他网站无法得到.此cookie由CsrfViewMiddleware产生.它 ...

  3. pg数据库数据表异常挂起

    pg数据库即是PostgreSQL数据库. 前几天在一个Java项目中,出现运行Java程序后,pg数据库的数据表异常挂起.而且是在某台电脑上出现的,重装数据库也没用,其它电脑未能复现,是个很奇怪的现 ...

  4. Eclipse 创建 Java 包---Eclipse教程第09课

    打开新建 Java 包向导 你可以使用新建 Java 包向导来创建 Java 包.Java 包向导打开方式有: 通过点击 "File" 菜单并选择 New > Package ...

  5. Xcode 代码提示功能失效

    前言: 以前好像很少碰到Xcode中代码提示出问题的情况,最近经常遇到这个问题.没有了Xcode的智能提示,发现我已完全不会写代码了. 本来想吐槽下万恶的baidu,鉴于百度前端时间的各种(贴吧.竞价 ...

  6. SQL Server无法连接到数据库

    连接数据库的时候出现如下错误: 我解决的使用方法: 第一步:关闭上面的错误,取消连接数据库. 第二步:开始->程序->Microsoft SQL Server 2008 R2->配置 ...

  7. cannot bind to 127.0.0.1:5037 报错

    使用appium连接真机时,提示这个错误,找了很久,发现是端口被占用 打开cmd,netstat -nao查看当前的TCP连接,找到使用127.0.0.1:5037的代码,然后到任务管理器查看详细进程 ...

  8. java 日期处理相关

    /** *获取指定日期 前后指定天数的 日期 * */ public static String getNewDate(String sdate, int days) throws Exception ...

  9. == 与 equals 之区别

    "=="和equals方法究竟有什么区别? (单独把一个东西说清楚,然后再说清楚另一个,这样,它们的区别自然就出来了,混在一起说,则很难说清楚) ==操作符专门用来比较两个变量的值 ...

  10. ctags+cscope替换sourceinsight

    背景 windows环境开发+linux交叉编译的开发模式,代码阅读和编写都用的source-insight. 除了检索,跳转,工程构建等方面,sourceinsight自带了一些宏语言,可以轻松实现 ...