背景

  在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. ubuntu安装wine 和sourceinsght

    ubuntu安装wine: 1.sudo apt-get update 2.sudo apt-get install wine 安装完成后会在当前用户目录的的家目录下生成.wine目录,该目录就是wi ...

  2. C语言实例解析精粹学习笔记——28

    实例28:从键盘读入实数 题目要求: 编制一个从键盘读入实数的函数readreal(double *rp).函数将读入的实数字符列转换成实数后,利用指针参数rp,将实数存于指针所指向的变量*rp. 思 ...

  3. [USACO12JAN]视频游戏的连击Video Game Combos(AC自动机+DP)

    Description 贝西正在打格斗游戏.游戏里只有三个按键,分别是“A”.“B”和“C”.游戏中有 N 种连击 模式,第 i 种连击模式以字符串 Si 表示,只要贝西的按键中出现了这个字符串,就算 ...

  4. spark stream简介

    1.复杂的迭代计算 假如我们计算的需要100步的计算,但是当我执行到第99步的时候,突然数据消失, 根据血统,从头进行恢复,代价很高 sc.setCheckpointDir("共享存储文件系 ...

  5. Android开发——弹性滑动的两种实现方式

    0. 前言   欢迎转载,转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52538723 我们在Android开发--View滑动的三 ...

  6. git 设置别名 git alias

    git config --global alias.st status git config --global alias.ck checkout git config --global alias. ...

  7. 【转】android makefile文件分析

    Makefile的规则如下: target ... : prerequisites ... command ... ... target可以是一个目标文件,也可以是Object File(例如hell ...

  8. 《Cracking the Coding Interview》——第2章:链表——题目3

    2014-03-18 02:25 题目:给定一个单链表中间的节点,删掉那个节点. 解法:把后面节点的数据域拷到当前节点来,然后删除后面那个节点.当前节点不是尾巴,所以后面不为空. 代码: // 2.2 ...

  9. Caliburn micro 学习笔记...

    页面跳转 LLS 结合 CM 使用方法 事件处理

  10. 【tmux环境配置】在centos6.4上配置tmux

    我学习tmux的动力如下: (1)tmux大法好.原因是被同学安利过tmux. (2)多个terminal下ssh到开发机太麻烦.还是之前实习的时候,总要开N个terminal去ssh开发机,这种东西 ...