using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication2
{
/// <summary>
/// 本例子通过双信号灯同步机制,演示两个后台线程如何同步工作,在窗口中打印出 "HelloX World!" 序列。
/// 具体功能如下:(注意:程序中凡有注释的语句都比较关键,勿遗漏。)
///
/// 1、线程1产生数据, 通过类变量简单地传递数据给线程2,而线程2则接收和处理数据;
/// 2、线程1、线程2不会出现失步,即:数据不重复处理、不漏处理、处理结果不重复显示、也不漏显示;
/// 3、线程2在后台如何跨线程访问 UI 元素;
///
/// 根据本文原理,读者完全可以对此类模式进行封装,实现更多个后台线程任务的同步工作能力。
/// 如有任何疑问,欢迎邮件(或MSN):appframework@hotmail.com,本人每周末会抽空答复。
/// </summary>
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Thread t1 = new Thread(ThreadStart1);
t1.IsBackground = true; // 放在后台运行,在主线程退出时才不会阻塞进程退出。
Thread t2 = new Thread(ThreadStart2);
t2.IsBackground = true; // 放在后台运行,在主线程退出时才不会阻塞进程退出。
// 通过双信号灯同步机制,以下两个工作线程的启动先后顺序可以随意。
t1.Start();
t2.Start();
}
/// <summary>
/// 自定义一个通用代理,供后续所有需要跨线程访问 UI 的地方使用。
/// </summary>
delegate void CrossThreadUIDelegate();
private string _syncBuffer = string.Empty;
/// <summary>
/// 在任务1完成时发出信号
/// </summary>
private AutoResetEvent _syncEvent1 = new AutoResetEvent(false);
/// <summary>
/// 在任务2完成时发出信号
/// </summary>
private AutoResetEvent _syncEvent2 = new AutoResetEvent(false);
public void ThreadStart1()
{
int i = 0;
while (true)
{
Thread.Sleep(1000);
_syncBuffer = "Hello" + (i++) + " "; // 设置数据
_syncEvent1.Set(); // 任务1完成了,设置标志给任务2放行
_syncEvent2.WaitOne(); // 等待任务2完成信号
}
}
/// <summary>
/// 后台线程,负责接收、处理和显示数据
/// </summary>
public void ThreadStart2()
{
while (true)
{
CrossThreadUIDelegate d = delegate()
{
textBox1.Text += _syncBuffer + "World!/r/n";
};
_syncEvent1.WaitOne(); // 等待任务1完成信号
try
{
textBox1.Invoke(d); // 跨线程访问 UI 元素
}
catch // 防止异常退出导致线程1无限等待
{
}
_syncEvent2.Set(); // 任务2完成,设置标志给任务1放行
}
}
}
}