系列目录:
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执行过程中,进度环会告诉用户现在正忙.这就很实用了.
水平有限,如有错误,还请指正!(系列结束,觉得又烂尾了,(*^_^*))