事件驱动异步模式
前言
啥叫事件?啥叫驱动?异步又是啥玩意?这些字一个一个的我都认识,但是练起来我就不知道啥意思了,别急,往下看.
在下一篇文章中,我会专门介绍并发,同步,异步以及事件驱动变成的相关技术.
Event-based asynchronous(EAP)在多线程的环境中提供了一个简单的处理方式.
它有以下几个特性
1.支持取消
2.可以安全的更新WPF或windows Form空间
3.在completion event中可以查询异常信息.
4.“在后台”执行耗时任务(例如下载和数据库操作),但不会终端您的应用程序
5.同时执行多个操作,每个操作完成时都会接到通知.
6.等待资源变得可用,但不会停止(“挂起”)你得应用程序
7.使用熟悉的事件和委托模型与挂起的异步操作通信
EAP仅仅是一个模式而已,所以这些特性必须都由实现者来实现.在.net中有少数几个类支持这种模式,最著名的就是BackgroundWorker和System.Net.WebClient了.
这个模式的本质是:每个类都提供了一些相似的成员来管理多线程,例如:
public byte[] DownloadData(Uri address);
public void DownloadDataAsync(Uri address);
public void DownloadDataAsync(Uri address, object userToken);
public event DownloadDataCompletedEventHandler DownloadDataCompleted;
public void CancelAsync(); //取消操作
public bool IsBusy { get; } //获取是否正在运行的信息。
下面是使用WebClient的例子:
class Program
{
static void Main(string[] argss)
{
var wc = new WebClient();
wc.DownloadStringCompleted += (sender, args) =>
{
if (args.Cancelled)
{
Console.WriteLine("Canceled");
}
else if (args.Error != null)
{
Console.WriteLine("Exception:" + args.Error.Message);
}
else
{
Console.WriteLine(args.Result.Length + " chars were downloaded");
}
};
wc.DownloadStringAsync(new Uri("http://www.cnblogs.com/LoveJenny/"));
Console.ReadLine();
}
}
分析:虽然一个WebClient有多个异步方法,但是因为他们都共享了相同的CancelAsyc和IsBusy属性,所以一次只能有一个异步操作.
BackgroundWorker
BackgroundWorker是System.ComponentModel下面的一个管理工作线程的帮助类,提供了下面几个特性.
1.支持取消
2.可以安全的更新WPF或windows Forms控件
3.在completion event中可以查询异常信息.
4.可以报告进度
5.因为实现了IComponent接口,所以可以被设计器使用.
6.BackgroundWorker使用了线程池,这意味着你永远都不能在一个BackgroundWorker线程上调用Abort方法.
class Program
{
static BackgroundWorker _bw = new BackgroundWorker();
public static void MainThread()
{
_bw.DoWork += new DoWorkEventHandler(_bw_DoWork);
_bw.RunWorkerAsync("Message to worker");
Console.ReadLine();
}
static void _bw_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine(e.Argument);
//做一些耗时的事情
for (int i = 0; i < 100000; i++)
{
Console.WriteLine(i);
}
}
static void Main(string[] argss)
{
MainThread();
Console.ReadLine();
}
}
下面的案例实现了进度报告
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace 事件异步
{
class Program
{
static void Main(string[] args)
{
ThreadBackgroundWorker.MainThread();
Console.ReadLine();
}
}
class ThreadBackgroundWorker
{
static BackgroundWorker _bw;
public static void MainThread()
{
_bw = new BackgroundWorker
{
WorkerReportsProgress=true,//允许报告进度
WorkerSupportsCancellation =true//允许取消
};
_bw.DoWork += new DoWorkEventHandler(_bw_DoWork);
_bw.ProgressChanged += new ProgressChangedEventHandler(_bw_ProgressChanged);
_bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_bw_RunWorkerCompleted);
_bw.RunWorkerAsync("hello to worker");
Console.WriteLine("Press Enter in the next 5 seconds to cancel.");
Console.ReadLine();
if (_bw.IsBusy)
{
_bw.CancelAsync();
}
Console.ReadLine();
}
static void _bw_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)//是否取消
{
Console.WriteLine("you canceled!");
}
else if (e.Error!=null)
{
Console.WriteLine("worker exception"+e.Error.ToString());
}
else
{
Console.WriteLine("Completed"+e.Result);
}
}
static void _bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//输出进度报告
Console.WriteLine("Reacher"+e.ProgressPercentage+"%");
}
static void _bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <=100; i+=20)
{
if (_bw.CancellationPending)
{
e.Cancel = true;
return;
}
_bw.ReportProgress(i);//报告进度
Thread.Sleep(1000);
}
e.Result = 123;
}
}
}
分析:虽然我不知道这是个什么玩意,想干嘛,但是看着输出感觉老酷了,好炫,如果用到其他地方,比如你在家在一个网页的时候,提示你加载情况,你在下片的时候提示你下了多少,如果用的好感觉很酷,本屌才疏学浅没啥学问,不知道如何应用,等到以后慢慢来吧.
小小的结一下
说实话,这些东西已经超出我的个人理解范围了,已经不明白是个啥意思了,但是还是硬着头皮看完了,因为我觉得这就像我小时候老师让我背过三字经一样,那个时候我才上小学1年级,字都认不全,更别说理解三字经啥意思了,但是我当时背过了,随着年龄的增长,我就慢慢理解啥意思了,我相信做学问也差不多,现在因为我不会,不懂,就不学,那肯定将来还是不会!