A、Thread,分两种,实例时带入一个委托,System.Threading.ThreadStart是无参数委托,System.Threading.ParameterizedThreadStart是带参数委托,这两个委托都是现成的
不带参数
Thread thread=new Thread(ThreadStart start);
带参数
Thread thread=new Thread(ParameterizedThreadStart start);
不带参数例子: 在form的label上刷新当前时间
Thread thread = new Thread(new ThreadStart(() =>
{
while (true)
this.Invoke(new MethodInvoker(() => { label1.Text = DateTime.Now.ToString(); }));
}));
thread.Start();
带参数例子 ParameterizedThreadStart委托带一个object的形参,说明带啥参数都是可以的
Thread thread = new Thread(new ParameterizedThreadStart((s) =>
{
while (true)
this.Invoke(new MethodInvoker(() => { label1.Text = (string)s + DateTime.Now.ToString(); }));
}));
thread.Start("带参数");
B、ThreadPool,线程池允许在后台运行多个工作,而不需要为每个任务频繁地创建和销毁单独的线程,从而减少了开销。此类是一个静态类 其静态方法 public static bool QueueUserWorkItem(WaitCallback callBack);用于将方法排入队列以便执行。此方法在有线程池线程变得可用时执行。WaitCallback也是个带object形参的现成委托和ParameterizedThreadStart类似
例子:直接把匿名方法扔进去就开始运行了,只是要注意线程池的可用值,可用即执行。
ThreadPool.QueueUserWorkItem(new WaitCallback((s) =>
{
while (true)
this.Invoke(new MethodInvoker(() => { label1.Text = (string)s + DateTime.Now.ToString(); }));
}), "带参数");
C、异步AsyncCallback 又是一个现成的委托,注意带入形参的类型是IAsyncResult,注意IAsyncResult这个接口下有个object AsyncState { get; }
例子:两个例子的区别只在AsyncState是什么?
1、
public partial class Form1 : Form
{
delegate void MyHandler(string s);
public Form1()
{
InitializeComponent();
MyHandler handler = new MyHandler((s) =>
{
for (int i = 0; i < 10000; i++)
this.Invoke(new MethodInvoker(() => { label1.Text = s + i.ToString(); }));
});
AsyncCallback callback = new AsyncCallback(MyCallBack);
handler.BeginInvoke("带参数", callback , handler); //注意第三个object类型的参数,其实就是AsyncState,所以把handler放进去在回调里显式转换一下就是委托了
}
public void MyCallBack(IAsyncResult ar) //回调函数,线程处理完执行的方法
{
((MyHandler)ar.AsyncState).EndInvoke(ar);
}
}
2、
public partial class Form1 : Form
{
delegate void MyHandler(string s);
public Form1()
{
InitializeComponent();
MyHandler handler = new MyHandler((s) =>
{
for (int i = 0; i < 10000; i++)
this.Invoke(new MethodInvoker(() => { label1.Text = s + i.ToString(); }));
});
AsyncCallback callback = new AsyncCallback(MyCallBack);
handler.BeginInvoke("带参数", callback , "回调完毕"); //此处第三个参数把AsyncState用来传值(或者直接设为null),回调方法里就不一样
}
public void MyCallBack(IAsyncResult ar) //回调函数,线程处理完执行的方法
{
MyHandler handler = (MyHandler)((AsyncResult)ar).AsyncDelegate;
handler.EndInvoke(ar);
this.Invoke(new MethodInvoker(() => { label1.Text += ar.AsyncState; }));
}
}
D、由C联想到文件IO的异步、网络的异步,其实大同小异
文件IO异步例子
public partial class Form1 : Form
{
const int bufferSize = 10;
byte[] data = new byte[bufferSize];
List<byte> totalData = new List<byte>();
AsyncCallback callback;
public Form1()
{
InitializeComponent();
FileStream fs = new FileStream("Test.txt", FileMode.Open, FileAccess.Read, FileShare.Read, 10240, true);
callback = new AsyncCallback(MyCallBack);
fs.BeginRead(data, 0, bufferSize, callback, fs);
//BeginRead背后的实现其实是这样的:ReadDelegate delegate2 = new ReadDelegate(this.Read); delegate2.BeginInvoke(buffer, offset, count, callback, state); 多么熟悉
}
public void MyCallBack(IAsyncResult ar)
{
FileStream fs = (FileStream)ar.AsyncState;
int bytesRead = fs.EndRead(ar);
if (bytesRead > 0)
{
fs.BeginRead(data, 0, bufferSize, callback, fs);
totalData.AddRange(data);
Array.Clear(data, 0, bufferSize);
}
else //读完一起显示
{
this.Invoke(new MethodInvoker(() => { label1.Text = Encoding.Default.GetString(totalData.ToArray()); }));
fs.Close();
}
}
}
网络接收的例子
public partial class Form1 : Form
{
const int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
AsyncCallback callback;
public Form1()
{
InitializeComponent();
ThreadPool.QueueUserWorkItem(new WaitCallback((o) =>
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
TcpListener listener = new TcpListener(ip, 8888);
listener.Start();
while (true) //循环处理,可以同时支持多个client
{
TcpClient client = listener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
callback = new AsyncCallback(MyCallBack);
stream.BeginRead(buffer, 0, bufferSize, callback, client);//最后一个参数把TcpClient放进去,回调中就可以分别处理不同的Client了
}
}));
}
public void MyCallBack(IAsyncResult ar)
{
TcpClient client = (TcpClient)ar.AsyncState; //把TcpClient取出来,AsyncState真是好东西
NetworkStream stream = client.GetStream();
int bytesRead = stream.EndRead(ar);
try
{
if (bytesRead > 0) //有数据
{
this.Invoke(new MethodInvoker(() => { label1.Text += Encoding.Unicode.GetString(buffer, 0, bytesRead); }));
Array.Clear(buffer, 0, buffer.Length);
}
stream.BeginRead(buffer, 0, bufferSize, callback, client);
}
catch (Exception)
{
if (stream != null)
stream.Dispose();
client.Close();
}
}
}
为了方便上面程序调试给个发送数据的例子
static void Main(string[] args)
{
TcpClient client;
try
{
client = new TcpClient();
client.Connect("localhost", 8888);
while (true)
{
string msg = Console.ReadLine();
NetworkStream stream = client.GetStream();
byte[] buffer = Encoding.Unicode.GetBytes(msg);
stream.Write(buffer, 0, buffer.Length);
Console.WriteLine("发送: {0}", msg);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
E、BackgroundWorker 也是用来执行多线程任务的一个控件,其有三个事件,用起来比较优雅,也经常配合进度条使用,ReportProgress会触发ProgressChanged事件,从而实现进度刷新
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true; //报告进度
worker.DoWork += (sender, e) =>
{
for (int i = 0; i <= 10000; i++)
this.Invoke(new MethodInvoker(() => { label1.Text = i.ToString(); worker.ReportProgress(i / 100, null); }));
};
worker.RunWorkerCompleted += (sender, e) =>
{
this.Invoke(new MethodInvoker(() => { label1.Text += "执行完毕"; }));
};
worker.ProgressChanged += (sender, e) =>
{
progressBar1.Style = ProgressBarStyle.Continuous;
progressBar1.Value = e.ProgressPercentage;
};
worker.RunWorkerAsync();