解决方案三个,成功解决timer组件和progressbar更新偶尔死机的问题
1、使用lock(Object)的方法来防止重入,表示一个Timer处理正在执行,下一个Timer发生的时候发现上一个没有执行完就等待执行,适用重入很少出现的场景(具体也没研究过,可能比较占内存吧)。
代码跟上面差不多,在触发的方法中加入lock,这样当线程2进入触发的方法中,发现已经被锁,会等待锁中的代码处理完在执行,代码如下:
1
2
3
4
5
6
7
8
|
private
static
object
locko =
new
object
();
/// <summary>
/// System.Timers.Timer的回调方法
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private
static
void
TimersTimerHandler(
object
sender, EventArgs args)
{
|
1
|
int
t = ++num; <br>
lock
(locko)
|
1
2
3
4
5
6
7
|
<em id=
"__mceDel"
> {
Console.WriteLine(
string
.Format(
"线程{0}输出:{1}, 输出时间:{2}"
, t, outPut.ToString(), DateTime.Now));
System.Threading.Thread.Sleep(2000);
outPut++;
Console.WriteLine(
string
.Format(
"线程{0}自增1后输出:{1},输出时间:{2}"
, t, outPut.ToString(), DateTime.Now));
}
}</em>
|
2、设置一个标志,表示一个Timer处理正在执行,下一个Timer发生的时候发现上一个没有执行完就放弃(注意这里是放弃,而不是等待哦,看看执行结果就明白啥意思了)执行,适用重入经常出现的场景。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
private
static
int
inTimer = 0;
/// <summary>
/// System.Timers.Timer的回调方法
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private
static
void
TimersTimerHandler(
object
sender, EventArgs args)
{
int
t = ++num;
if
(inTimer == 0)
{
inTimer = 1;
Console.WriteLine(
string
.Format(
"线程{0}输出:{1}, 输出时间:{2}"
, t, outPut.ToString(), DateTime.Now));
System.Threading.Thread.Sleep(2000);
outPut++;
Console.WriteLine(
string
.Format(
"线程{0}自增1后输出:{1},输出时间:{2}"
, t, outPut.ToString(), DateTime.Now));
inTimer = 0;
}
}
|
3、在多线程下给inTimer赋值不够安全,Interlocked.Exchange提供了一种轻量级的线程安全的给对象赋值的方法(感觉比较高上大,也是比较推荐的一种方法),执行结果与方法2一样,也是放弃执行。Interlocked.Exchange用法参考这里。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
private
static
int
inTimer = 0;
/// <summary>
/// System.Timers.Timer的回调方法
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private
static
void
TimersTimerHandler(
object
sender, EventArgs args)
{
int
t = ++num;
if
(Interlocked.Exchange(
ref
inTimer, 1) == 0)
{
Console.WriteLine(
string
.Format(
"线程{0}输出:{1}, 输出时间:{2}"
, t, outPut.ToString(), DateTime.Now));
System.Threading.Thread.Sleep(2000);
outPut++;
Console.WriteLine(
string
.Format(
"线程{0}自增1后输出:{1},输出时间:{2}"
, t, outPut.ToString(), DateTime.Now));
Interlocked.Exchange(
ref
inTimer, 0);
}
}
|