没有说说新的async ctp吗?
时间:2010-10-30 来源:jjx
有一个任务需要10秒才能完成
private int getTotalBytes(){
Thread.Sleep(10000);
return 1000;
}
传统的同步方法
在这10秒间,ui会被冻结,ui不会有响应,通常这是我们要避免的
有多种方法解决这个问题,线程,异步(异步实际上也是利用了线程池)或者是.net 4中的Task(其实也是线程包装),并且要考虑其他线程调用主线程ui上的问题(win forms 依赖ISynchronizeInvoke机制)
1. 用线程
代码 Thread t = new Thread(() => {int result = getTotalBytes();
Invoke(new Action(()=>{
textBox1.Text = result.ToString();
}));
});
t.Start();
2. 异步回调
异步方法主要借助于deletage 的BeginInvoke和EndInvoke,看起来代码更加复杂些
Func<int> t = getTotalBytes;
t.BeginInvoke(new AsyncCallback((arg)=>{
AsyncResult _result = (AsyncResult)arg;
Func<int> _t =(Func<int>) _result.AsyncDelegate;
string _s=_t.EndInvoke(arg).ToString();
this.Invoke(new Action(() => { textBox1.Text = _s; }));
}), null);
3. windows forms 中提供了一个backgroundWorker,从某种程度上简化异步方法的调用,他提供DoWork和RunWorkerCompleted两个事件,一个用来执行任务,一个用来做执行结果的处理,他能自动处理不同线程上调用主线程中ui组件的问题
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (sender1, e1) =>
{
e1.Result = getTotalBytes();
};
worker.RunWorkerCompleted += (sender2, e2) =>
{
textBox1.Text = e2.Result.ToString();
};
worker.RunWorkerAsync();
在silverlight 中处理的手法也是类似的,同windows forms 不同,silverlight 更多的依赖异步处理,这同它host在浏览器环境中有关,因此,有些框架的api都有异步版本,如ExecuteSync,然后通过回调处理返回结果,如
Dispatcher.BeginInvoke(()=>{gridView.ItemsSource=arg.Results;});
});
在.net 4中,引入了Task这个概念,新的async ctp 建立在Task这个基础之上
简单的说await 这个新的关键字能等待Task<T>的执行完成并取得结果,在新的async,await 模式中,代码变得很简单
{
Task<int> t = new Task<int>(() =>
{
return getTotalBytes();
});
t.Start();
textBox3.Text = (await t).ToString();
}
async/await其实需要框架做一些调整,从早先的ExecuteSync 接受一个回调 ,到现在要返回一个或多个已经开始的Task<T>实例,所以,早期的框架要修改才能适应这个关键字,不过自己的代码,就可以使用这种模式来简化编程了。