ManualResetEvent类的使用
通知一个或多个正在等待的线程已发生事件。 此类不能被继承。
构造函数
public ManualResetEvent(
bool initialState
)
initialState
类型:System.Boolean
如果为 true,则将初始状态设置为终止;如果为 false,则将初始状态设置为非终止。
如果 ManualResetEvent 的初始状态是终止状态(即,如果其通过为 initialState 传递true 创建),则等待 ManualResetEvent 的线程不阻塞。 如果初始状态为非终止状态,则线程调用 Set 方法后才不阻塞。
方法
Reset 将事件状态设置为非终止状态,导致线程阻止。 (继承自 EventWaitHandle。)
Set 将事件状态设置为终止状态,允许一个或多个等待线程继续。 (继承自 EventWaitHandle。)
Set 将事件状态设置为终止状态,允许一个或多个等待线程继续。 (继承自 EventWaitHandle。)
WaitOne()
阻止当前线程,直到当前 WaitHandle 收到信号。
终止状态时WaitOne()允许线程访问下边的语句
非终止状态时WaitOne()阻塞线程,不允许线程访问下边的语句
下面是一个实现Http下载的例子
public class DownloadProcessor { public ManualResetEvent allDone = new ManualResetEvent(false); const int BUFFER_SIZE = 1024; public byte[] Download(string url, DownloadProgressHandler progressCB)//下载函数 { // 保证标志设置正确.<span style="white-space:pre"> </span> allDone.Reset();//执行到WaitOne后,下面的语句会阻塞 //从命令行当中获取url. Uri httpPath = new Uri(url); //创建请求对象. WebRequest req = WebRequest.Create(httpPath); //创建状态对象. DownloadDetail detail = new DownloadDetail(); //将请求放入状态对象以便能够被传递. detail.webRequest = req; //给回调函数赋值 detail.ProgressCallback += progressCB; //声明异步请求. IAsyncResult r = (IAsyncResult)req.BeginGetResponse(new AsyncCallback(ResponseCallback), detail); //一直阻塞直到ManualResetEvent被置记号,即下载完毕时才继续向下执行 allDone.WaitOne(); //将下载的信息传递回去. if (detail.useBuffers) return detail.BufferFast; else { byte[] data = new byte[detail.BufferSlow.Count]; for (int b = 0; b < detail.BufferSlow.Count; b++) data[b] = (byte)detail.BufferSlow[b]; return data; } } private void ResponseCallback(IAsyncResult iar) { //从async中得到DownloadInfo对象 DownloadDetail detail = (DownloadDetail)iar.AsyncState; //从RequestState中得到WebRequest. WebRequest webreq = detail.webRequest; //调用创建WebResponse对象的EndGetResponse WebResponse webresp = webreq.EndGetResponse(iar); //从头中找到数据尺寸. string strLength = webresp.Headers["Content-Length"]; if (strLength != null) { detail.Length = Convert.ToInt32(strLength); detail.BufferFast = new byte[detail.Length]; } else { detail.useBuffers = false; detail.BufferSlow = new System.Collections.ArrayList(BUFFER_SIZE); } //开始从response流中读取数据 Stream ResponseStream = webresp.GetResponseStream(); // 将response stream存储在RequestState当中异步地去读取流 detail.responseStream = ResponseStream; // 将do.BufferRead传递给BeginRead. IAsyncResult iarRead = ResponseStream.BeginRead(detail.Read, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), detail); } private void ReadCallBack(IAsyncResult asyncResult) { //从AsyncResult得到DownloadInfo对象. DownloadDetail detail = (DownloadDetail)asyncResult.AsyncState; //回收在RespCallback中设置的ResponseStream. Stream responseStream = detail.responseStream; // 读info.BufferRead来验证是否包含数据. int bytesRead = responseStream.EndRead(asyncResult); if (bytesRead > 0)//数据没有读取完毕,则继续读取 { if (detail.useBuffers) { System.Array.Copy(detail.Read, 0, detail.BufferFast, detail.bytes, bytesRead); } else { for (int b = 0; b < bytesRead; b++) detail.BufferSlow.Add(detail.Read[b]); } detail.bytes += bytesRead; // 如果进程回调,则通知进度条 if (detail.ProgressCallback != null) detail.ProgressCallback(detail.bytes, detail.Length); // 一直读数据直到responseStream.EndRead返回 IAsyncResult ar = responseStream.BeginRead( detail.Read, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), detail); } else { responseStream.Close(); allDone.Set();//下载完毕,将事件状态设置为终止状态,WaitOne后面的语句可以执行 } return; } }
版权声明: