这个问题不太容易说明白,主要的思路是把整个异步操作过程分为若干段,每一段完成后判断条件,如果条件成立又调用自己,否则终止操作。下面是我以前写的代码,这个类的功能是下载文件,每下载1k它就会引发OnProgress事件,你可以在事件中设置事件参数DownLoadEventArgs的IsCancel属性来决定是否终止下载。
using System;
using System.IO;
using System.Net;
using System.Windows.Forms;
using System.ComponentModel;
using System.Threading;namespace DownLoadControl
{
public class DownLoadEventArgs : EventArgs
{
private bool isCancel;//设置是否终止的标志
private long bytesRecieved;
public long BytesRecieved     //接收字节数
{
set {bytesRecieved=value;}
get {return bytesRecieved;}
} private long totalBytes;
public long TotalBytes  //总字节数
{
set {totalBytes=value;}
get {return totalBytes;}
}
public bool IsCancel
{
set {isCancel=value;}
get {return isCancel;}
} }
class DownLoadInfo
{
private long bytesRead=0;
public long BytesRead  
{
set {bytesRead=value;}
get {return bytesRead;}
}
private long bytesTotal=-1;
public long BytesTotal
{
set {bytesTotal=value;}
get {return bytesTotal;}
}
public byte[] bytesBuffer=new byte[1024];
private WebRequest request=null;
public WebRequest Request
{
set {request=value;}
get {return request;}
}
private Stream responseStream=null;
public Stream ResponseStream
{
set {responseStream=value;}
get {return responseStream;}
} }

public class DownLoadControl:Component
{
public delegate void Complete(object sender,DownLoadEventArgs e);
public delegate void Progress(object sender,DownLoadEventArgs e); public event Complete OnComplete;   //下载完成事件
public event Progress OnProgress;    //下载进度事件 private DownLoadInfo downLoadInfo=null;
private FileStream downLoadStream=null;
private ManualResetEvent allDone=new ManualResetEvent(false);
        
public DownLoadControl()
{
downLoadInfo=new DownLoadInfo();
}
protected void CompleteDownLoad(IAsyncResult ar)
{
       
WebResponse response=downLoadInfo.Request.EndGetResponse(ar);
downLoadInfo.ResponseStream=response.GetResponseStream();
downLoadInfo.BytesTotal=Convert.ToInt64(response.Headers["Content-Length"]);//获取需要下载的总字节数
    
downLoadInfo.ResponseStream.BeginRead(downLoadInfo.bytesBuffer,0,1024,new AsyncCallback(DownLoadProgress),downLoadInfo);
}
protected void DownLoadProgress(IAsyncResult ar)
{

int dataRead=downLoadInfo.ResponseStream.EndRead(ar);
if (dataRead>0)
{
downLoadStream.Write(downLoadInfo.bytesBuffer,0,downLoadInfo.bytesBuffer.Length);
downLoadInfo.BytesRead+=dataRead;
if (this.OnProgress!=null)
{
DownLoadEventArgs args=new DownLoadEventArgs();
args.TotalBytes=downLoadInfo.BytesTotal;
args.BytesRecieved=downLoadInfo.BytesRead;
this.OnProgress(this,args);
                                                                                if (args.IsCancel)//如果被终止,退出
                                                                               {
                                                                                downLoadInfo.ResponseStream.Close();
                                  downLoadStream.Close();
                        allDone.Set();
                                                                                return;
                                                                                }
}
downLoadInfo.ResponseStream.BeginRead(downLoadInfo.bytesBuffer,0,1024,new AsyncCallback(DownLoadProgress),downLoadInfo);
}
else
{
downLoadInfo.ResponseStream.Close();
downLoadStream.Close();
allDone.Set();
}

}
protected void DownLoad()
{
try
{
downLoadInfo.Request=WebRequest.Create(new Uri(this.URL)); //建立连接
}
catch (Exception E)
{
MessageBox.Show(E.Message);
return;
}
catch 
{
MessageBox.Show("无法建立连接");
return;
}
if (File.Exists(this.Distination))
{
if (MessageBox.Show("","文件"+this.Distination+"已经存在,是否代替原文件?",MessageBoxButtons.YesNo)==DialogResult.No)
return;
}
try
{
downLoadStream=File.Create(this.Distination);
}
catch (Exception E)
{
MessageBox.Show(E.Message);
return;
}
catch 
{
MessageBox.Show("无法建立指定的文件");
return;
}
allDone.Reset();

downLoadInfo.Request.BeginGetResponse(new AsyncCallback(CompleteDownLoad),downLoadInfo); //开始接收数据
allDone.WaitOne();
if (this.OnComplete!=null)
{
DownLoadEventArgs args=new DownLoadEventArgs();
args.TotalBytes=downLoadInfo.BytesTotal;
args.BytesRecieved=downLoadInfo.BytesRead;
this.OnProgress(this,args);
} } public void Start()
{
System.Threading.Thread a=new System.Threading.Thread(new System.Threading.ThreadStart(this.DownLoad));  //新建一个线程
a.Start();    //开始下载
}
#region 属性
private string url;
public string URL
{
set {url=value;}
get {return url;}
}
private string distination;
public string Distination
{
set {distination=value;}
get {return distination;}
}
public long BytesRead
{
get {return downLoadInfo.BytesRead;}
}
public long BytesTotal
{
get {return downLoadInfo.BytesTotal;}
}
#endregion
}
}

解决方案 »

  1.   

    上面的方法固然可行,也有一个很好的方法就是
    Thread.Abort函数
      

  2.   

    发出一个 BeginInvoke 后,如何重新获取对这个异步调用线程的控制?
    如能,当然就很容易的使用 Thread.Abort() 方法来中止它。
    我无法设定异步调用的 Id ,不然可以从线程池中确定它了。首先谢谢各位,这么快就有回复了。