在AE数据处理过程中,数据量往往不小,单线程处理往往由于主线程阻滞导致用户就不能进行其他操作了,还会出现假死的状态。因此前端出现一个等待窗体或者进度条,在后台线程处理数据是很有必要的!
今天计划实现这样的一个功能,使用BackgroundWorker来实现。首先还是要参考已有的例子!(水平低,没办法啊!)
http://msdn.microsoft.com/zh-cn/library/b2zk6580(v=vs.85).aspx
View Code
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace BackgroundWorkerExample
{
public class FibonacciForm : System.Windows.Forms.Form
{
private int numberToCompute = 0;
private int highestPercentageReached = 0;
private System.Windows.Forms.NumericUpDown numericUpDown1;
private System.Windows.Forms.Button startAsyncButton;
private System.Windows.Forms.Button cancelAsyncButton;
private System.Windows.Forms.ProgressBar progressBar1;
private System.Windows.Forms.Label resultLabel;
private System.ComponentModel.BackgroundWorker backgroundWorker1;
public FibonacciForm()
{
InitializeComponent();
InitializeBackgoundWorker();
}
// Set up the BackgroundWorker object by
// attaching event handlers.
private void InitializeBackgoundWorker()
{
backgroundWorker1.DoWork +=
new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(
backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.ProgressChanged +=
new ProgressChangedEventHandler(
backgroundWorker1_ProgressChanged);
}
private void startAsyncButton_Click(System.Object sender,
System.EventArgs e)
{
// Reset the text in the result label.
resultLabel.Text = String.Empty;
// Disable the UpDown control until
// the asynchronous operation is done.
this.numericUpDown1.Enabled = false;
// Disable the Start button until
// the asynchronous operation is done.
this.startAsyncButton.Enabled = false;
// Enable the Cancel button while
// the asynchronous operation runs.
this.cancelAsyncButton.Enabled = true;
// Get the value from the UpDown control.
numberToCompute = (int)numericUpDown1.Value;
// Reset the variable for percentage tracking.
highestPercentageReached = 0;
// Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync(numberToCompute);//这里传入需要后台处理的数据参数numberToCompute
//这句话很重要,我把DataTable导入ITable工作包装成一个类,在这句话之前将类的各个属性赋值,然后将该类作为参数传入
}
private void cancelAsyncButton_Click(System.Object sender,
System.EventArgs e)
{
// Cancel the asynchronous operation.
this.backgroundWorker1.CancelAsync();
// Disable the Cancel button.
cancelAsyncButton.Enabled = false;
}
// This event handler is where the actual,
// potentially time-consuming work is done.
private void backgroundWorker1_DoWork(object sender,
DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;
// Assign the result of the computation
// to the Result property of the DoWorkEventArgs
// object. This is will be available to the
// RunWorkerCompleted eventhandler.
e.Result = ComputeFibonacci((int)e.Argument, worker, e);//这里通过e.Argument获取异步操作的参数数据,通过强制转换获得类对象,在该方法中实现功能。
}
// This event handler deals with the results of the
// background operation.
private void backgroundWorker1_RunWorkerCompleted(
object sender, RunWorkerCompletedEventArgs e)
{
// First, handle the case where an exception was thrown.
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
// Next, handle the case where the user canceled
// the operation.
// Note that due to a race condition in
// the DoWork event handler, the Cancelled
// flag may not have been set, even though
// CancelAsync was called.
resultLabel.Text = "Canceled";
}
else
{
// Finally, handle the case where the operation
// succeeded.
resultLabel.Text = e.Result.ToString();
}
// Enable the UpDown control.
this.numericUpDown1.Enabled = true;
// Enable the Start button.
startAsyncButton.Enabled = true;
// Disable the Cancel button.
cancelAsyncButton.Enabled = false;
}
// This event handler updates the progress bar.
private void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
}
// This is the method that does the actual work. For this
// example, it computes a Fibonacci number and
// reports progress as it does its work.实际后台运行的函数,负责计算斐波那契数列
long ComputeFibonacci(int n, BackgroundWorker worker, DoWorkEventArgs e)
{
// The parameter n must be >= 0 and <= 91.
// Fib(n), with n > 91, overflows a long.
if ((n < 0) || (n > 91))
{
throw new ArgumentException(
"value must be >= 0 and <= 91", "n");
}
long result = 0;
// Abort the operation if the user has canceled.
// Note that a call to CancelAsync may have set
// CancellationPending to true just after the
// last invocation of this method exits, so this
// code will not have the opportunity to set the
// DoWorkEventArgs.Cancel flag to true. This means
// that RunWorkerCompletedEventArgs.Cancelled will
// not be set to true in your RunWorkerCompleted
// event handler. This is a race condition.
if (worker.CancellationPending)
{
e.Cancel = true;
}
else
{
if (n < 2)
{
result = 1;
}
else
{
result = ComputeFibonacci(n - 1, worker, e) +
ComputeFibonacci(n - 2, worker, e);
}
// Report progress as a percentage of the total task.
int percentComplete =
(int)((float)n / (float)numberToCompute * 100);
if (percentComplete > highestPercentageReached)
{
highestPercentageReached = percentComplete;
worker.ReportProgress(percentComplete);
}
}
return result;
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
this.startAsyncButton = new System.Windows.Forms.Button();
this.cancelAsyncButton = new System.Windows.Forms.Button();
this.resultLabel = new System.Windows.Forms.Label();
this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
this.SuspendLayout();
//
// numericUpDown1
//
this.numericUpDown1.Location = new System.Drawing.Point(16, 16);
this.numericUpDown1.Maximum = new System.Decimal(new int[] {
91,
0,
0,
0});
this.numericUpDown1.Minimum = new System.Decimal(new int[] {
1,
0,
0,
0});
this.numericUpDown1.Name = "numericUpDown1";
this.numericUpDown1.Size = new System.Drawing.Size(80, 20);
this.numericUpDown1.TabIndex = 0;
this.numericUpDown1.Value = new System.Decimal(new int[] {
1,
0,
0,
0});
//
// startAsyncButton
//
this.startAsyncButton.Location = new System.Drawing.Point(16, 72);
this.startAsyncButton.Name = "startAsyncButton";
this.startAsyncButton.Size = new System.Drawing.Size(120, 23);
this.startAsyncButton.TabIndex = 1;
this.startAsyncButton.Text = "Start Async";
this.startAsyncButton.Click += new System.EventHandler(this.startAsyncButton_Click);
//
// cancelAsyncButton
//
this.cancelAsyncButton.Enabled = false;
this.cancelAsyncButton.Location = new System.Drawing.Point(153, 72);
this.cancelAsyncButton.Name = "cancelAsyncButton";
this.cancelAsyncButton.Size = new System.Drawing.Size(119, 23);
this.cancelAsyncButton.TabIndex = 2;
this.cancelAsyncButton.Text = "Cancel Async";
this.cancelAsyncButton.Click += new System.EventHandler(this.cancelAsyncButton_Click);
//
// resultLabel
//
this.resultLabel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.resultLabel.Location = new System.Drawing.Point(112, 16);
this.resultLabel.Name = "resultLabel";
this.resultLabel.Size = new System.Drawing.Size(160, 23);
this.resultLabel.TabIndex = 3;
this.resultLabel.Text = "(no result)";
this.resultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// progressBar1
//
this.progressBar1.Location = new System.Drawing.Point(18, 48);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(256, 8);
this.progressBar1.Step = 2;
this.progressBar1.TabIndex = 4;
//
// backgroundWorker1
//
this.backgroundWorker1.WorkerReportsProgress = true;
this.backgroundWorker1.WorkerSupportsCancellation = true;
//
// FibonacciForm
//
this.ClientSize = new System.Drawing.Size(292, 118);
this.Controls.Add(this.progressBar1);
this.Controls.Add(this.resultLabel);
this.Controls.Add(this.cancelAsyncButton);
this.Controls.Add(this.startAsyncButton);
this.Controls.Add(this.numericUpDown1);
this.Name = "FibonacciForm";
this.Text = "Fibonacci Calculator";
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
this.ResumeLayout(false);
}
#endregion
[STAThread]
static void Main()
{
Application.Run(new FibonacciForm());
}
}
}
这段代码是微软MSDN中的一个计算斐波那契数列的例子,采用的是BackgroundWorker异步线程操作。这段代码可以直接保存运行,运行界面如下:
这里分析的是如何实现AE数据处理中的应用,首先看看BackgroundWorker组件的属性和事件,加粗的就是经常会用到的。
思路就是把DataTable数据转换到ITable所需的参数和方法包装成一个类DataTable2ITable,
View Code
1 class DataTable2ITable
2 {
3 private string columnX;
4
5 public string ColumnX
6 {
7 get { return columnX; }
8 set { columnX = value; }
9 }
10 private string columnY;
11
12 public string ColumnY
13 {
14 get { return columnY; }
15 set { columnY = value; }
16 }
17 private string iTablename;
18
19 public string ITablename
20 {
21 get { return iTablename; }
22 set { iTablename = value; }
23 }
24 private DataTable dt;
25
26 public DataTable Dt
27 {
28 get { return dt; }
29 set { dt = value; }
30 }
31 private string strWsp;
32
33 public string StrWsp
34 {
35 get { return strWsp; }
36 set { strWsp = value; }
37 }
38 private ISpatialReference pSpatialReference;
39
40 public ISpatialReference SpatialReference
41 {
42 get { return pSpatialReference; }
43 set { pSpatialReference = value; }
44 }
45 public IFeatureClass CreateFeatureTable()
46 {
47 IList<IFieldInfo> listFieldinfos = new List<IFieldInfo>();
48 IFieldInfo m_OID=new OIDField();//OID字段
49 listFieldinfos.Add(m_OID);
50 IFieldInfo m_FieldGeo = new GeomtryField();
51 IGeomtryInfo pGeoInfo = m_FieldGeo as IGeomtryInfo;
52 pGeoInfo.GeometryType = esriGeometryType.esriGeometryPoint;
53 pGeoInfo.HasZ = false;
54 pGeoInfo.SpatialReference = pSpatialReference;
55 listFieldinfos.Add(m_FieldGeo);
56 foreach (DataColumn dc in dt.Columns)
57 {
58 IFieldInfo m_Holefield1 = new TableField();//表的其他字段
59 switch (dc.DataType.Name)
60 {
61 case "String":
62 m_Holefield1.Name_2 = dc.ColumnName;
63 m_Holefield1.AliasName_2 = dc.Caption;
64 m_Holefield1.Type_2 = esriFieldType.esriFieldTypeString;
65 m_Holefield1.Length_2 = dc.MaxLength;
66 break;
67 case "Single":
68 m_Holefield1.Name_2 = dc.ColumnName;
69 m_Holefield1.AliasName_2 = dc.Caption;
70 m_Holefield1.Type_2 = esriFieldType.esriFieldTypeSingle;
71 m_Holefield1.Precision_2 = 2;
72 break;
73 case "Double":
74 m_Holefield1.Name_2 = dc.ColumnName;
75 m_Holefield1.AliasName_2 = dc.Caption;
76 m_Holefield1.Type_2 = esriFieldType.esriFieldTypeDouble;
77 m_Holefield1.Precision_2 = 2;
78 break;
79 case "Int16":
80 m_Holefield1.Name_2 = dc.ColumnName;
81 m_Holefield1.AliasName_2 = dc.Caption;
82 m_Holefield1.Type_2 = esriFieldType.esriFieldTypeSmallInteger;
83 m_Holefield1.Length_2 = 16;
84 break;
85 case "Int32":
86 m_Holefield1.Name_2 = dc.ColumnName;
87 m_Holefield1.AliasName_2 = dc.Caption;
88 m_Holefield1.Type_2 = esriFieldType.esriFieldTypeSmallInteger;
89 m_Holefield1.Length_2 = 32;
90 break;
91 case "Int64":
92 m_Holefield1.Name_2 = dc.ColumnName;
93 m_Holefield1.AliasName_2 = dc.Caption;
94 m_Holefield1.Type_2 = esriFieldType.esriFieldTypeInteger;
95 m_Holefield1.Length_2 = 64;
96 break;
97 default:
98 m_Holefield1.Name_2 = dc.ColumnName;
99 m_Holefield1.AliasName_2 = dc.Caption;
100 m_Holefield1.Type_2 = esriFieldType.esriFieldTypeString;
101 m_Holefield1.Length_2 = 255;
102 break;
103
104 }
105 listFieldinfos.Add(m_Holefield1);
106 }
107 GFieldsInfo m_fieldsinfo=new GFieldsInfo(listFieldinfos);
108 IFields m_fields = m_fieldsinfo.CreateFieldsForTable();
109 IFeatureClass m_featurecls= GCreateNewFeatureClass.CreateNewAccessFeatureClass(strWsp, iTablename, m_fields);
110 return m_featurecls;
111 //CloneDataTable(m_featurecls);
112 }
113 public void CloneDataRow(IFeatureClass m_featurecls,DataRow dr)
114 {
115 //foreach (DataRow dr in dt.Rows)
116 //{
117 IFeature m_feature = m_featurecls.CreateFeature();
118 double x=Convert.ToDouble(dr[columnX]);
119 double y=Convert.ToDouble(dr[columnY]);
120 IPoint pt=new PointClass();
121 pt.PutCoords(x,y);
122 m_feature.Shape = pt as IGeometry;
123 for (int i=0; i<dt.Columns.Count;i++)
124 {
125 int j=m_feature.Fields.FindField(dt.Columns[i].ColumnName);
126 m_feature.set_Value(j, dr[i]);
127 }
128 m_feature.Store();
129 //}
130
131 }
DoWork事件和后台执行函数代码:
View Code
1 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
2 {
3 BackgroundWorker worker = sender as BackgroundWorker;
4 DataTable2ITable m_dt2IdtAsync = e.Argument as DataTable2ITable;
5 e.Result = ComputeFibonacci(m_dt2IdtAsync, worker, e);
6
7 }
8 int highestPercentageReached=0;
9 long ComputeFibonacci(DataTable2ITable m_dt2IdtAsync, BackgroundWorker worker, DoWorkEventArgs e)
10 {
11 IFeatureClass pfeaturecls= m_dt2IdtAsync.CreateFeatureTable();
12 int n = 0;
13 foreach ( DataRow dr in m_Dt.Rows)
14 {
15 m_dt2IdtAsync.CloneDataRow(pfeaturecls, dr);
16 n++;
17 int percentComplete = (int)((float)n / (float)m_Dt.Rows.Count * 100);
18 if (percentComplete > highestPercentageReached)
19 {
20 highestPercentageReached = percentComplete;
21 worker.ReportProgress(percentComplete);
22 }
23 }
24 return 100;
25
26 }
运行界面: