我现在要多线程方式访问一个全局的值,这个值必需是全局唯一的。(假设是 int类型)
从0开始以1步进递增。就是说,不管哪个线程进来,得到的这个值,都别跟别的线程得到的不一样。
从0开始以1步进递增。就是说,不管哪个线程进来,得到的这个值,都别跟别的线程得到的不一样。
解决方案 »
- winform自定义控件的Mouse事件、无法实现自动、求助
- 用string.Replace()替换反斜杠"\"
- 已有打开的与此命令相关联的 DataReader,必须首先将它关闭。
- 求一动态的添加treenode的节点的方法,高手进.
- 写了一Windform程序遇到关于dataGridView绑定问题.急急急急急急急
- comboBox1绑定dataset以后,如何取出Item的值。
- 关于动态加载多个带参数用户自定义控件问题,新人第一次提问题多多支持啦!
- 新人报道~~再求一个C#方面的入门书籍~
- 文件上传,分不够可再给
- 关于contextMenu控件的问题!
- 请教如何把树形表的数据动态添加到treeview中,救命贴
- 类库调用webservice
加了锁,别的线程进来,如果是一个Asp.Net程序的一个客户端请求呢?我怎么回应,或者设置线程等待?
我刚试了,这个好像可以;但如果我要获取的值不是int类型呢?可能是字母组合A~Z{n}
我只是举个例子嘛,要真是的话,我全一个全局静态的变量就行了,反正加一下也不花多长时间;我的意思是说“如果这个值生成的过程需要一定的时间,比如10秒种,而在上一个线程进行的时候,另一个线程进来了,我怎么让它等会儿?如果这个线程是Asp.net Request产生的,这个时候,我该怎么回应这个请求呢?还是不用回应?直接让线程等待就行了?”
我其实是想找一个比较完善的解决办法的,既然这样,那我说实际的吧。需求:我现在要生成一个编号这个编号的格式是“特定的Id号_年月日_一个全局唯一的编号”,这个编号要每天0点0分0时0秒初始化成0,并且,同一天里,不同特定Id号等到的全局唯一编号不能相同。这个编号的请求,是Asp.Net页面完成的。这个页面的访问量可能在同一时间产生很多个申请这个编号的进程。
初始化的问题,我可以用SqlServer的定时“事务”来解决。就是将这个值存到一个表的字段里,每天定时设置成0。其实这样也不保险,如果那个时间正好有客户请求呢?但我目前也只想到这个办法。另外一个重点问题,如果一个访问者的请求还没有完成,其它N个访问者的请求就已经来了,这个时候我怎么办呢?
第二个,如果一个访问者的请求还没有完成,其它的进来了,会等待,直到锁被释放后进去一个,其余的继续等待,直到全部完成,这是正常的,你什么都不用做。
先发上我的解决办法,如果有问题请回帖指出来,三天后结帖: /// <summary>
/// 稿件编号驱动工厂
/// <para>稳定</para>
/// </summary>
public static class NumberProviderFactory
{
/// <summary>
/// 全局稿件编号驱动
/// </summary>
private static INumberProvider GlobalNumberProvider; /// <summary>
/// 获取一个INumberProvider实例
/// <para>单例模式,全局唯一</para>
/// </summary>
/// <param name="configFilePath">文档配置文件路径</param>
/// <returns></returns>
public static INumberProvider GetNumberProvider(string configFilePath)
{
if (GlobalNumberProvider == null)
{
GlobalNumberProvider = new NumberProvider(configFilePath);
}
return GlobalNumberProvider;
}
} /// <summary>
/// 稿件编号驱动接口
/// </summary>
public interface INumberProvider
{
/// <summary>
/// 访问线程计数器
/// </summary>
int VisitorCounter { get; } /// <summary>
/// 获取当前串号
/// </summary>
/// <returns></returns>
int GetCurrent(); /// <summary>
/// 重置当前串号为0
/// </summary>
void Reset();
} /// <summary>
/// 稿件编号驱动
/// </summary>
public class NumberProvider : INumberProvider
{
/// <summary>
/// xml配置文件的路径
/// </summary>
private string xmlPath = string.Empty; /// <summary>
/// 单线程排它锁
/// </summary>
private Mutex AppLocker = new Mutex(); private int _VisitorCounter;
/// <summary>
/// 访问线程计数器
/// </summary>
public int VisitorCounter
{
get { return this._VisitorCounter; }
} #region private int CurrentNumber { get; set; }
/// <summary>
/// 获取或设置当前串号
/// </summary>
private int CurrentNumber
{
get
{
try
{
XmlDocument xd = new XmlDocument();
xd.Load(xmlPath);
XmlNode xn = xd.SelectSingleNode("/document/numberseed/value");
if (xn != null)
return int.Parse(xn.InnerText);
return 0;
}
catch
{
return -1;
}
}
set
{
try
{
XmlDocument xd = new XmlDocument();
xd.Load(xmlPath); XmlNode xn = xd.SelectSingleNode("/document/numberseed/value");
if (xn != null)
xn.InnerText = value.ToString(); xd.Save(xmlPath);
}
catch { }
}
}
#endregion /// <summary>
/// 使用当前应用程序指定的配置文件计数
/// </summary>
/// <param name="configFilePath">文档配置文件路径</param>
public NumberProvider(string configFilePath)
{
if (string.IsNullOrEmpty(configFilePath))
this.xmlPath = HttpRuntime.AppDomainAppPath + "documentconf.xml";
else
this.xmlPath = configFilePath; this._VisitorCounter = 0;
} #region public virtual int GetCurrent()
/// <summary>
/// 获取当前串号
/// </summary>
/// <returns></returns>
public virtual int GetCurrent()
{
this._VisitorCounter++;
AppLocker.WaitOne(); try
{
CurrentNumber++;
return CurrentNumber;
}
finally
{
AppLocker.ReleaseMutex();
this._VisitorCounter--;
}
}
#endregion #region public virtual void Reset()
/// <summary>
/// 重置当前串号为0,并更新统计日期
/// </summary>
public virtual void Reset()
{
this._VisitorCounter++;
AppLocker.WaitOne(); try
{
CurrentNumber = 0;
XmlDocument xd = new XmlDocument();
xd.Load(xmlPath);
XmlNode xn = xd.SelectSingleNode("/document/numberseed/date");
if (xn != null)
xn.InnerText = DateTime.Now.Date.ToString("yyyy-MM-dd");
xd.Save(xmlPath);
}
finally
{
AppLocker.ReleaseMutex();
this._VisitorCounter--;
}
}
#endregion
} public class Global : System.Web.HttpApplication
{
/// <summary>
/// 稿件编号控制器
/// </summary>
Timer NumberControler; /// <summary>
/// 控制器同步句柄
/// </summary>
AutoResetEvent NumberContorlerHandle = new AutoResetEvent(false); protected void Application_Start(object sender, EventArgs e)
{
DateTime nextDayStart = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.AddDays(1).Day, 0, 0, 0); //当前与下一天开始时间的时间差
TimeSpan diff = nextDayStart - DateTime.Now; TimerCallback tc = new TimerCallback(ResetNumberCount);
NumberControler = new Timer(tc, NumberContorlerHandle, diff, new TimeSpan(24, 0, 0));
} /// <summary>
/// 初始化稿件编号
/// </summary>
/// <param name="o"></param>
protected void ResetNumberCount(object o)
{
AutoResetEvent are = (AutoResetEvent)o;
NumberProviderFactory.GetNumberProvider(HttpRuntime.AppDomainAppPath + "documentconf.xml").Reset();
are.Set();
}
}