昨天下午看俺的神的视频,同声中文说的是一团雾水,前面讲的是async以及避免ui冻结的问题。后来下载的async ctp,大致看了一下,多了两个关键字async/await ,看样子又是语法糖,但这个语法糖非常的有用,代码一下子清晰许多了。举个例子,将一个需要长时间执行任务的结果显示在一个文本框中,如下

 

有一个任务需要10秒才能完成

   private int getTotalBytes()
        {
            Thread.Sleep(
10000);
            
return 1000;
        }

 

 

     


传统的同步方法


textBox1.Text=getTotalBytes();

 

 


在这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,然后通过回调处理返回结果,如


db.Categories.ExecuteSync(arg=>{

Dispatcher.BeginInvoke(()
=>{gridView.ItemsSource=arg.Results;});

});

 

 


在.net 4中,引入了Task这个概念,新的async ctp 建立在Task这个基础之上



简单的说await 这个新的关键字能等待Task<T>的执行完成并取得结果,在新的async,await 模式中,代码变得很简单



代码
 private async void button3_Click(object sender, EventArgs e)
        {
            Task
<int> t = new Task<int>(() =>
            {
                
return getTotalBytes();

            });
            t.Start();
            
            textBox3.Text 
= (await t).ToString();
        }
 

 

 

 

async/await其实需要框架做一些调整,从早先的ExecuteSync 接受一个回调 ,到现在要返回一个或多个已经开始的Task<T>实例,所以,早期的框架要修改才能适应这个关键字,不过自己的代码,就可以使用这种模式来简化编程了。

posted on 2010-10-30 10:42  jjxstudio  阅读(1045)  评论(1编辑  收藏  举报