| 
 | 
	
 
 
  [源码下载] 
 
 
 
 
重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换   
作者:webabcd 
 
介绍 
重新想象 Windows 8 Store Apps 之 异步编程 
 
 
- 经典的异步编程模型(IAsyncResult)
 
 - 最新的异步编程模型(async 和 await)
 
 - 将 IAsyncInfo 转换成 Task
 
 - 将 Task 转换成 IAsyncInfo
 
     
示例 
1、使用经典的异步编程模型(IAsyncResult)实现一个支持异步操作的类 
Thread/Async/ClassicAsync.cs 
 
 
 
/* 
* 使用经典的异步编程模型(IAsyncResult)实现一个支持异步操作的类 
*/ 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 
namespace XamlDemo.Thread.Async 
{ 
public class ClassicAsync 
{ 
private delegate string HelloDelegate(string name); 
private HelloDelegate _helloDelegate; 
public ClassicAsync() 
{ 
_helloDelegate = new HelloDelegate(Hello); 
} 
private string Hello(string name) 
{ 
new ManualResetEvent(false).WaitOne(3000); 
return "hello: " + name; 
} 
// begin 方法 
public IAsyncResult BeginRun(string name, AsyncCallback callback, Object state) 
{ 
// 新开线程,去执行 Hello() 方法,callback 是回调,state 是上下文 
return _helloDelegate.BeginInvoke(name, callback, state); 
} 
// end 方法 
public string EndRun(IAsyncResult ar) 
{ 
if (ar == null) 
throw new NullReferenceException("IAsyncResult 不能为 null"); 
return _helloDelegate.EndInvoke(ar); 
} 
} 
} 
  Thread/Async/ClassicAsyncDemo.xaml 
 
 
 
 
 
 
 
 
 
 
 
  Thread/Async/ClassicAsyncDemo.xaml.cs 
 
 
 
/* 
* 演示如何通过经典的异步编程模型(IAsyncResult)来进行异步操作 
*  
* IAsyncResult - 异步操作结果 
*     AsyncState - 上下文 
*     IsCompleted - 异步操作是否已完成 
*     AsyncWaitHandle -  获取用于等待异步操作完成的 System.Threading.WaitHandle 对象(通过 WaitHandle.WaitOne() 在当前线程等待) 
*/ 
using System; 
using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 
namespace XamlDemo.Thread.Async 
{ 
public sealed partial class ClassicAsyncDemo : Page 
{ 
System.Threading.SynchronizationContext _syncContext; 
public ClassicAsyncDemo() 
{ 
this.InitializeComponent(); 
// 获取当前 UI 线程 
_syncContext = System.Threading.SynchronizationContext.Current; 
} 
private void btnIAsyncResult_Click_1(object sender, RoutedEventArgs e) 
{ 
ClassicAsync classicAsync = new ClassicAsync(); 
IAsyncResult ar = classicAsync.BeginRun("webabcd", new AsyncCallback(Callback), classicAsync); 
lblMsg.Text = "开始执行,3 秒后完成"; 
} 
private void Callback(IAsyncResult ar) 
{ 
ClassicAsync classicAsync = (ClassicAsync)ar.AsyncState; 
string result = classicAsync.EndRun(ar); 
_syncContext.Post( 
(ctx) => 
{ 
lblMsg.Text = result; 
}, 
null); 
} 
} 
} 
   
2、演示如何通过最新的异步编程模型(async 和 await)来进行异步操作 
Thread/Async/NewAsyncDemo.xaml 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  Thread/Async/NewAsyncDemo.xaml.cs 
 
 
 
/* 
* 演示如何通过最新的异步编程模型(async 和 await)来进行异步操作 
*  
* 注: 
* 1、要想 await,其所在方法必须标记为 async 
* 2、方法被标记为 async 是为了让编译器重新编写该方法,使 await 中的内容重新编写为具有 GetAwaiter() 等实际异步逻辑的代码 
*/ 
using System; 
using System.Threading; 
using System.Threading.Tasks; 
using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 
namespace XamlDemo.Thread.Async 
{ 
public sealed partial class NewAsyncDemo : Page 
{ 
private static int _count = 0; 
public NewAsyncDemo() 
{ 
this.InitializeComponent(); 
} 
// 不带返回值的 Task 
private async Task TaskWithoutReturn() 
{ 
// 在另一个线程 sleep 1000 毫秒,然后回到 UI 线程 
await Task.Delay(1000); 
// await Task.Delay(Timeout.Infinite); 长眠于此 
// await Task.Delay(Timeout.InfiniteTimeSpan); 长眠于此 
// 直接在当前线程 sleep 可以使用如下方法,因为 WinRT 中没有 Thread.Sleep() 了 
// new ManualResetEvent(false).WaitOne(1000); 
 
Interlocked.Increment(ref _count); 
} 
// 带返回值的 Task 
private async Task TaskWithReturn() 
{ 
await Task.Delay(1000); 
Interlocked.Increment(ref _count); 
return _count; 
} 
// 演示不带返回值的异步操作 
private async void btnTaskWithoutReturn_Click_1(object sender, RoutedEventArgs e) 
{ 
// ConfigureAwait(false) - 异步操作后不返回 UI 线程,可节省一点点资源。默认值:ConfigureAwait(true) 
await TaskWithoutReturn().ConfigureAwait(false); 
lblMsg.Text = "count: " + _count.ToString(); 
} 
// 演示带返回值的异步操作 
private async void btnTaskWithReturn_Click_1(object sender, RoutedEventArgs e) 
{ 
int result = await TaskWithReturn(); 
lblMsg.Text = "count: " + result.ToString(); 
} 
// 演示多任务并行执行的异步操作 
private async void btnMultiTask_Click_1(object sender, RoutedEventArgs e) 
{ 
Task task = Task.WhenAll(TaskWithoutReturn(), TaskWithoutReturn(), TaskWithoutReturn()); 
DateTime dt = DateTime.Now; 
await task; 
lblMsg.Text = "count: " + _count.ToString() + ", 执行时间: " + (DateTime.Now - dt).TotalSeconds.ToString() + "秒"; 
} 
// 演示如何执行一个不 await 的 Task 
private void btnTaskWithoutAwait_Click_1(object sender, RoutedEventArgs e) 
{ 
// 让 task 在新线程执行去吧,本线程不管它是什么执行情况 
Task task = TaskWithoutReturn(); 
lblMsg.Text = "count: " + _count.ToString(); 
} 
} 
} 
   
3、演示如何将 IAsyncInfo(IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress) 转成 Task 
Thread/Async/IAsyncInfo2Task.xaml 
 
 
 
 
 
 
 
 
 
 
  Thread/Async/IAsyncInfo2Task.xaml.cs 
 
 
 
/* 
* 演示如何将 IAsyncInfo(IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress) 转成 Task 
*/ 
using System; 
using System.Runtime.InteropServices.WindowsRuntime; 
using System.Threading; 
using System.Threading.Tasks; 
using Windows.Foundation; 
using Windows.UI.Xaml.Controls; 
using Windows.UI.Xaml.Navigation; 
namespace XamlDemo.Thread.Async 
{ 
public sealed partial class IAsyncInfo2Task : Page 
{ 
public IAsyncInfo2Task() 
{ 
this.InitializeComponent(); 
} 
protected async override void OnNavigatedTo(NavigationEventArgs e) 
{ 
// 用于取消 Task 
CancellationTokenSource cts = new CancellationTokenSource(); 
// 创建一个 IAsyncInfo 
IAsyncOperation action = AsyncInfo.Run( 
(token) => 
Task.Run( 
() => 
{ 
token.WaitHandle.WaitOne(3000); 
token.ThrowIfCancellationRequested(); 
return 10 * 10; 
}, 
token)); 
lblMsg.Text = "开始执行,3 秒后完成"; 
// 将 IAsyncOperation 转换成 Task 
// AsTask() 是扩展方法,其逻辑在 System.WindowsRuntimeSystemExtensions 类中 
Task task = action.AsTask(cts.Token); 
int result = await task; 
lblMsg.Text = "结果:" + result.ToString(); 
} 
} 
} 
   
4、演示如何将 Task 转成 IAsyncInfo(IAsyncAction, IAsyncOperation) 
Thread/Async/Task2IAsyncInfo.xaml 
 
 
 
 
 
 
 
 
 
 
  Thread/Async/Task2IAsyncInfo.xaml.cs 
 
 
 
/* 
* 演示如何将 Task 转成 IAsyncInfo(IAsyncAction, IAsyncOperation) 
*/ 
using System; 
using System.Threading; 
using System.Threading.Tasks; 
using Windows.Foundation; 
using Windows.UI.Xaml.Controls; 
using Windows.UI.Xaml.Navigation; 
namespace XamlDemo.Thread.Async 
{ 
public sealed partial class Task2IAsyncInfo : Page 
{ 
public Task2IAsyncInfo() 
{ 
this.InitializeComponent(); 
} 
protected async override void OnNavigatedTo(NavigationEventArgs e) 
{ 
// 用于取消 IAsyncInfo(注意:本例中的 IAsyncInfo 是从 Task 转换过来的,所以 IAsyncInfo.Cancel() 方法无效) 
CancellationTokenSource cts = new CancellationTokenSource(); 
// 创建一个 Task 
Task task = Task.Run( 
() => 
{ 
cts.Token.WaitHandle.WaitOne(3000); 
cts.Token.ThrowIfCancellationRequested(); 
return 10 * 10; 
}, 
cts.Token); 
lblMsg.Text = "开始执行,3 秒后完成"; 
// 将 Task 转换成 IAsyncOperation 
// AsAsyncAction(), AsAsyncOperation() 是扩展方法,其逻辑在 System.WindowsRuntimeSystemExtensions 类中 
IAsyncOperation operation = task.AsAsyncOperation(); 
int result = await operation; 
lblMsg.Text = "结果:" + result.ToString();            
} 
} 
} 
   
OK 
[源码下载] |   
 
 
 
 | 
  
 |