Winform程序(4.0以上)异步获取数据时常用的方法可能如下:
private void button3_Click(object sender, EventArgs e)
{
DataTable dt = null;
Task.Factory.StartNew(() =>
{
dt = new DataTable();
dt.Columns.Add("id", typeof(int));
dt.Columns.Add("name");
for (int i = 0; i < 10000; i++)
{
dt.Rows.Add(new object[] { i, "name" + i.ToString() });
}
Thread.Sleep(5000);
this.Invoke((EventHandler)delegate
{
this.dataGridView1.DataSource = dt;
});
});
}
传统方法也比较一目了然,但既然有了await/async,我们应该优先使用await/async,毕竟其它语言(js,c++)现在也都提供了await/async语法,习惯了await/async写法,在写前后端的数据异步处理时会容易上手。下面代码基于.net framework4.6.1实现
private void button2_Click(object sender, EventArgs e)
{
//由于.net461的Button控件没有实现 ISynchronizeInvoke接口,所以要用下面的代码过渡一下
_ = AsyncFunc();
}
async Task AsyncFunc()
{
DataTable dt = await FecthData();
this.dataGridView1.DataSource = dt;
}
async Task<DataTable> FecthData()
{
DataTable dt=null;
await Task.Run(() =>
{
dt = new DataTable();
dt.Columns.Add("id", typeof(int));
dt.Columns.Add("name");
for (int i = 0; i < 10000; i++)
{
dt.Rows.Add(new object[] { i, "name" + i.ToString() });
}
Thread.Sleep(5000);
});
return dt;
}
为了便于理解,我们可以简单认为 await 就是个代码执行分裂点,本例中当执行到下面的代码时:
await Task.Run(() =>
主线程会启动线程池中线程执行 Task.Run中的Action,并且编译器会在这里打一个“标记”点,Action代码执行完毕后线程池中线程会通知主线程到“标记”点继续向下执行。
js是单线程模式,用promise实现了async/await,但是用c#的实现方法去理解js的async/await的执行顺序也是没有问题的。