利用BackgroundWorker控件异步读取shp文件
在WinForm中,当执行一些耗时任务时,因响应时间较长而导致窗体假死是一种常见问题。这时我们往往会想到单独开一个线程执行任务,同时显示当前任务的执行进度。但.NET并不允许跨线程访问UI,因为UI都是创建在主线程当中的,若跨线程访问会导致不可预计的问题出现。较为常用的是利用委托,把更新UI状态的代码Invoke到主线程,这是较为常用的一种方法。除此之外,WinForm提供了一个BackgroundWorker组件,它能够使我们更加简单地实现异步读取的功能。这里利用ArcEngine读取shp文件,同时利用BackgroundWorker组件防止界面假死。代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Output;
using ESRI.ArcGIS.SystemUI;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private IFeatureClass pFeatureClass;
// 构造函数
public Form1()
{
InitializeComponent();
pFeatureClass = GetFeatureClass(@"D:\Users\DSF\Desktop\data\ZD.shp");
pgbReadStatus.Maximum = pFeatureClass.FeatureCount(null);
}
// 执行任务
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, true);
IFeature pFeature = pFeatureCursor.NextFeature();
while (pFeature != null)
{
if (bw.CancellationPending)
{
e.Cancel = true;
break;
}
// YSDM
int fieldIndex_YSDM = pFeature.Fields.FindField("YSDM");
string fieldValue_YSDM = pFeature.get_Value(fieldIndex_YSDM).ToString();
// DKMC
int fieldIndex_DKMC = pFeature.Fields.FindField("DKMC");
string fieldValue_DKMC = pFeature.get_Value(fieldIndex_DKMC).ToString();
// DKBM
int fieldIndex_DKBM = pFeature.Fields.FindField("DKBM");
string fieldValue_DKBM = pFeature.get_Value(fieldIndex_DKBM).ToString();
// 报告进度
bw.ReportProgress(pFeature.OID);
pFeature = pFeatureCursor.NextFeature();
}
}
// 显示进度
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pgbReadStatus.Value = e.ProgressPercentage;
}
// 取消任务
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.ToString());
return;
}
if (e.Cancelled)
{
MessageBox.Show("终止");
}
else
{
MessageBox.Show("完成");
}
}
// 获取要素类
private IFeatureClass GetFeatureClass(string filePath)
{
IWorkspaceFactory pWorkspaceFactory = new ShapefileWorkspaceFactory();
IWorkspaceFactoryLockControl pWorkspaceFactoryLockControl = pWorkspaceFactory as IWorkspaceFactoryLockControl;
if (pWorkspaceFactoryLockControl.SchemaLockingEnabled)
{
pWorkspaceFactoryLockControl.DisableSchemaLocking();
}
IWorkspace pWorkspace = pWorkspaceFactory.OpenFromFile(System.IO.Path.GetDirectoryName(filePath), 0);
IFeatureWorkspace pFeatureWorkspace = pWorkspace as IFeatureWorkspace;
IFeatureClass pFeatureClass = pFeatureWorkspace.OpenFeatureClass(System.IO.Path.GetFileName(filePath));
return pFeatureClass;
}
// 开始
private void btnStart_Click(object sender, EventArgs e)
{
if (bw.IsBusy)
{
return;
}
bw.RunWorkerAsync();
}
// 取消
private void btnCancel_Click(object sender, EventArgs e)
{
bw.CancelAsync();
}
// 关闭窗体
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
bw.CancelAsync();
}
}
}
加过如下:
当读取shp文件时,仍旧可以随意拖动窗体。在处理耗时操作时,可以考虑使用BackgroundWorker组件。
转载自:https://blog.csdn.net/HerryDong/article/details/86486557