使用BackgroundWorker 实现文件下载、异步提示
2008-10-31 14:47:19 来源:不详 作者:佚名 点击:
最近在做一个IIS日志分析的系统,由于日志文件是在服务器上,但是分析需要放到客户端进行(为了提高性能和安全性),第一步就是需要将日志文件从服务器上下载到客户机上,可以通过控制台程序实现些功能,并且这个下载过程应该是自动化的不需要人工干预。
最近在做一个IIS日志分析的系统,由于日志文件是在服务器上,但是分析需要放到客户端进行(为了提高性能和安全性),第一步就是需要将日志文件从服务器上下载到客户机上,可以通过控制台程序实现些功能,并且这个下载过程应该是自动化的不需要人工干预。
准备做一个可视化的WinForm界面,这就需要反映文件下载进度,要达到这个实时报告进度的功能,就需要进行异步操作,可以通过线程或BackgroundWorker 类去实现, 由于BackgroundWorker 类是.net2.0新增的组件类,所以就先通过一个小实例来体验一下BackgroundWorker的使用方法,以后面的文章中将会给出使用线程的方法。
我们先来了解BackgroundWorker 类的基本功能:
在单独的线程上执行操作,此类是.net2.0新增的类,在.net1.1上不能使用(只能使用线程实现相同功能)。如果有一个需要很长时间才能完成的操作,而且不希望用户界面中出现延迟,则可以使用BackgroundWorker类来在另一个线程上运行该操作。
BackgroundWorker 类允许您在单独的专用线程上运行操作。耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态。如果您需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 BackgroundWorker 类方便地解决问题。
若要在后台执行耗时的操作,请创建一个 BackgroundWorker ,侦听那些报告操作进度并在操作完成时发出信号的事件。可以通过编程方式创建 BackgroundWorker ,也可以将它从 “工具箱” 的 “组件” 选项卡中拖到窗体上。如果在 Windows 窗体设计器中创建 BackgroundWorker ,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。
若要设置后台操作,请为 DoWork 事件添加一个事件处理程序。在此事件处理程序中调用耗时的操作。若要启动该操作,请调用 RunWorkerAsync 。若要收到进度更新通知,请对 ProgressChanged 事件进行处理。若要在操作完成时收到通知,请对 RunWorkerCompleted 事件进行处理。
说明:您必须非常小心,确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。BackgroundWorker 事件不跨 AppDomain 边界进行封送处理。请不要使用 BackgroundWorker 组件在多个 AppDomain 中执行多线程操作。
如果后台操作需要参数,请在调用 RunWorkerAsync 时给出参数。在 DoWork 事件处理程序内部,可以从 DoWorkEventArgs..::.Argument 属性中提取该参数。
下面我们一起来看实现过程,若大家发现有不对的地方,请指导,可以到我的blog留言
运行界面:
核心代码:
-
private
void
btn_down_Click(
object
sender, EventArgs e)
-
{
-
-
backgroundWorker1.WorkerReportsProgress =
true
;
-
-
backgroundWorker1.WorkerSupportsCancellation =
true
;
-
-
-
backgroundWorker1.RunWorkerAsync(
"ready go"
);
-
-
this
.btn_cancel.Enabled =
true
;
-
this
.btn_down.Enabled =
false
;
-
}
-
-
private
void
btn_cancel_Click(
object
sender, EventArgs e)
-
{
-
-
this
.backgroundWorker1.CancelAsync();
-
this
.btn_cancel.Enabled =
false
;
-
this
.btn_down.Enabled =
true
;
-
}
-
private
void
backgroundWorker1_DoWork(
object
sender, DoWorkEventArgs e)
-
{
-
-
BackgroundWorker worker = sender
as
BackgroundWorker;
-
-
-
-
object
obj = e.Argument;
-
-
-
-
e.Result = DownLoadLog(worker, e);
-
}
-
-
private
void
backgroundWorker1_ProgressChanged(
object
sender, ProgressChangedEventArgs e)
-
{
-
-
this
.progressBar1.Value = e.ProgressPercentage;
-
this
.lbl_msg.Text =
string
.Format(
"下载已完成{0}%,{1}M/{2}M"
, e.ProgressPercentage, (Math.Round(
decimal
.Parse(e.UserState.ToString()) / (
decimal
)(1024 * 1024),2)).ToString(), _fileSize.ToString());
-
}
-
-
private
void
backgroundWorker1_RunWorkerCompleted(
object
sender, RunWorkerCompletedEventArgs e)
-
{
-
-
if
(e.Error !=
null
)
-
{
-
MessageBox.Show(e.Error.Message);
-
}
-
else
if
(e.Cancelled)
-
{
-
-
-
-
-
-
-
-
this
.lbl_msg.Text =
"下载被取消!"
;
-
}
-
else
-
{
-
-
-
this
.lbl_msg.Text =
bool
.Parse(e.Result.ToString()) ?
"下载成功!"
:
"下载失败!"
;
-
}
-
-
btn_down.Enabled =
true
;
-
-
btn_cancel.Enabled =
false
;
-
}
-
-
-
-
-
-
-
private
bool
DownLoadLog(BackgroundWorker worker, DoWorkEventArgs e)
-
{
-
long
maxFileSize = ftp.GetFileSize(_remoteFileName);
-
_fileSize = Decimal.Round(((
decimal
)maxFileSize / (
decimal
)1024) / (
decimal
)1024, 2);
-
-
-
return
ftp.Get(_remoteFileName, _localFolder, _localFileName, maxFileSize, worker, e);
-
}