系列目录:
1.委托和事件绑定
2.泛型委托
3.委托和多线程
NET的线程池管理是很复杂的一套东西,使用Task对线程进行友好的访问是很必要。Task在MSDN上有详细的介绍:https://msdn.microsoft.com/zh-cn/library/system.threading.tasks.task.aspx 如果看了前面介绍泛型委托会有帮助理解Task任务.
这里简单介绍一些简单的Task使用方式.
Task用于构造那些耗时运算,例如网络连接类等。观察下面的代码:
namespace Turtual { public class AboutTask { public AboutTask() { // 这里虽然没有await,但Task是开辟新线程的,因此不会阻塞UI string result =GetResource("url","content=1").Result; // 主线程会直接继续,此时result是空的,不可用,因为Task还没有执行完毕 } async void Dowork() { //如果想要等待任务完成,必须使用await/async关键字 string result = await GetResource("url", "content=1"); //会等待Task执行完成result,此时Result有值可以使用 } //一个典型的任务方法 public async Task<string> GetResource(string url, string para) { //模拟一个耗时操作 string InfoUrl = "http://cn.bing.com/HPImageArchive.aspx?idx=0&n=1"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(InfoUrl); request.Method = "GET"; request.ContentType = "text/html;charset=UTF-8"; string XmlString; using (WebResponse response = await request.GetResponseAsync()) { Stream myResponseStream = response.GetResponseStream(); using (StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8)) { XmlString = myStreamReader.ReadToEnd(); } } return XmlString; } } }
上面的代码显示了Task任务简单的应用,Task使得整个过程可控,代码简洁而优美.刚接触Task语法我们自己不一定会写那些那些可等待的任务,但是需要学会使用系统的提供的可等待的方法,从上面的例子中我们可以看到这个过程并不难,甚至超出了以往的体验,拥抱Task以及await/async异步关键字.我刚开始有个疑惑,await/async异步关键字成对出现,await是等待的意思,那不是阻塞线程执行了么,其实从委托一路看过来就会明白,无论是否等待Task一定是新开线程或者回收旧线程,不会阻塞主线程.使用await的好处就是,如果需要使用异步的执行结果,那就需要等待.否则就不用.一般情况下,能用await就尽量使用await.在windows10通用应用里面所有的对话框是异步操作的,下面看看UWP中典型的弹出对话框是怎么使用await的吧!
//登陆 private async void LoginButton_Click(object sender, RoutedEventArgs e) { if (App.IsLogin == false) { LoginDialog login = new LoginDialog(); await login.ShowAsync(); switch (login.Result) { case SignInResult.SignInOK: App.IsLogin = true; App.username = login.username; App.password = login.password; //(sender as AppBarButton).Label = "上传"; await GetCloudFiles();//加载云数据 break; case SignInResult.SignInFail: MessageDialog popup = new MessageDialog(AppResources.GetString("LoginFailed")); await popup.ShowAsync(); break; case SignInResult.SignInCancel: break; case SignInResult.Nothing: break; default: break; } } else { MessageDialog md = new MessageDialog(AppResources.GetString("LoginSuccess")); await md.ShowAsync(); } }
使用了await方法,调用登陆对话框弹出,此时下面的代码都在等await结束,才能执行.在自定义的用户控件上面,使用远程的登陆Task.
namespace EasyNote { public enum SignInResult { SignInOK, SignInFail, SignInCancel, Nothing } public sealed partial class LoginDialog : ContentDialog,INotifyPropertyChanged { private bool _Isbusy=false; public bool IsBusy { get { return _Isbusy; } set { SetProperty(ref _Isbusy,value); } } public SignInResult Result { get; private set; } public string username; public string password; //实现INotify接口------------------------------------ public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged([CallerMemberName] String propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void OnPropertyChanged([CallerMemberName] string propertyName = "") { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null) { if (object.Equals(storage, value)) return false; storage = value; this.OnPropertyChanged(propertyName); return true; } //设置 public UserSetting ClientSetting=new UserSetting(); //属性 public bool? SaveUserName { get { return ClientSetting.SaveUserName; } set { ClientSetting.SaveUserName = (bool)value; NotifyPropertyChanged(); } } private string _UserName; public string UserName { get { if (_UserName==null) { _UserName = ClientSetting.UserName; } return _UserName; } set { if (SaveUserName!=false) { ClientSetting.UserName = value; } _UserName = value; NotifyPropertyChanged(); } } public string _PassWord; public string PassWord { get { if (_PassWord == null) { _PassWord = ClientSetting.PassWord; } return _PassWord; } set { if (SaveUserName != false) { ClientSetting.PassWord = value; } _PassWord = value; NotifyPropertyChanged(); } } public LoginDialog() { this.InitializeComponent(); //保存的设置 } //登陆 private async void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) { ContentDialogButtonClickDeferral deferral = args.GetDeferral(); if (string.IsNullOrEmpty(userNameTextBox.Text)) { args.Cancel = true; errorTextBlock.Text = "User name is required."; } else if (string.IsNullOrEmpty(passwordTextBox.Password)) { args.Cancel = true; errorTextBlock.Text = "Password is required."; } await Login(); deferral.Complete(); } public async Task Login() { IsBusy = true; username = userNameTextBox.Text; password = passwordTextBox.Password; notecloud.EasyNoteCloudSoapClient client = new notecloud.EasyNoteCloudSoapClient(); if ((await client.LoginAsync(username, password))) { this.Result = SignInResult.SignInOK; } else { this.Result = SignInResult.SignInFail; } IsBusy = false; } //取消 private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) { this.Result = SignInResult.SignInCancel; } } }
上面的代码有趣的地方在于定义了一个IsBusy属性,并且使用了数据绑定绑定到界面的ProgressRing的IsActive属性,在Task执行过程中,进度环会告诉用户现在正忙.这就很实用了.
水平有限,如有错误,还请指正!(系列结束,觉得又烂尾了,(*^_^*))