博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Winform 模拟Session
阅读量:4612 次
发布时间:2019-06-09

本文共 4838 字,大约阅读时间需要 16 分钟。

背景

  在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
dic = new Dictionary
(); 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 = 10) { 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 = 0; cache.ar.Set(); } } } }}

 问题  

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

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

转载于:https://www.cnblogs.com/codealone/p/3228077.html

你可能感兴趣的文章
软件自动化测试——入门、进阶与实战
查看>>
BZOJ1878 [SDOI2009]HH的项链 树状数组 或 莫队
查看>>
BZOJ3675 [Apio2014]序列分割 动态规划 斜率优化
查看>>
2016.10.24 继续学习
查看>>
产品功能对标 - 服务授权管理
查看>>
各地IT薪资待遇讨论
查看>>
splay入门
查看>>
带CookieContainer进行post
查看>>
C语言学习笔记--字符串
查看>>
CSS-上下文选择器
查看>>
ionic repeat 重复最后一个时要执行某个函数
查看>>
1.初识代码审计-基础
查看>>
[Vue-rx] Stream an API using RxJS into a Vue.js Template
查看>>
解决VC几个编译问题的方法——好用
查看>>
SPOJ #11 Factorial
查看>>
City Upgrades
查看>>
“人少也能办大事”---K2 BPM老客户交流会
查看>>
关于七牛进行图片添加文字水印操作小计
查看>>
DataSource数据库的使用
查看>>
CentOS开启samba实现文件共享
查看>>