在现代应用程序中,依赖于互联网连接来执行业务层操作,如调用网络服务、获取数据等,是很常见的需求。通常,开发者希望了解当前环境是否真的连接到了互联网。虽然可以通过检查每个NetworkInterface
的状态来实现这一点,但这并不能保证有可用的互联网连接。本文将展示一种在StatusStrip
上显示计算机是否连接到互联网的简单方法。
要实现这个功能,可以使用一个定时器(Timer
)来执行HTTP-GET请求,以检查特定网站是否可用。为了避免阻塞当前UI线程,使用BackgroundWorker
对象来执行查询。BackgroundWorker
对象声明了DoWork
方法,该方法定义了一个自定义事件处理程序,用于将实际结果传回UI线程。非常重要的一点是,不要尝试在此方法中与任何UI元素交互,因为它是在单独的线程上运行的。
首先,需要初始化BackgroundWorker
和Timer
对象。
private void InitializeComponent()
{
// Background Worker
this._worker = new BackgroundWorker();
this._worker.WorkerReportsProgress = false;
this._worker.WorkerSupportsCancellation = false;
this._worker.DoWork += new DoWorkEventHandler(this.BackgroundWorker_DoWork);
this._worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BackgroundWorker_RunWorkerCompleted);
// Timer
this._updateTimer = new Timer();
this._updateTimer.Enabled = !this.DesignMode;
this._updateTimer.Tick += delegate {
this.OnTick();
};
}
接下来,定义定时器的事件处理程序。在这个方法中,将停止定时器,禁用UI元素,并在单独的线程上执行网络查询。
private void OnTick()
{
if (this.DesignMode)
return;
this._updateTimer.Enabled = false;
this.Enabled = false;
this.Invalidate();
this._worker.RunWorkerAsync();
}
网络查询非常简单,对一个始终可用的URL执行简单的HttpWebRequest
。例如,可以使用公司网站、http://www.microsoft.com
或http://www.google.com
。这是实际检测是否有可用互联网连接的唯一方法。
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(this._alwaysAvailableUrl);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (HttpStatusCode.OK == response.StatusCode)
{
response.Close();
e.Result = true;
}
else
{
e.Result = false;
}
}
catch (WebException)
{
e.Result = false;
}
}
当BackgroundWorker
对象完成其工作后,它会调用RunWorkerCompleted
事件,该事件也定义了一个自定义事件处理程序,用于管理ToolStripStatusLabel
的渲染方式。
private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (null != e.Error)
{
Trace.TraceError(e.Error.Message);
throw e.Error;
}
else
{
if ((bool)e.Result)
{
this.Image = Properties.Resources.Online;
this.Text = Properties.Resources.MainFormConnectionStatusOnline;
}
else
{
this.Image = Properties.Resources.Offline;
this.Text = Properties.Resources.MainFormConnectionStatusOffline;
}
this.Invalidate();
this.Enabled = true;
this._updateTimer.Enabled = true;
}
}
.NET Framework2.0使得使用后台线程变得非常容易,为UI提供了流畅且有用的体验。如果使用的是Visual Studio .NET 2005的四月CTP版本,强烈建议手动为DoWork
事件分配委托,因为VS.NET中存在一个bug,当它尝试重写不使用UI代码的注释时,可能会替换掉实际的代码。