[源碼下載]
html
做者:webabcd
介紹
從新想象 Windows 8 Store Apps 之 異步編程html5
示例
一、使用經典的異步編程模型(IAsyncResult)實現一個支持異步操做的類
Thread/Async/ClassicAsync.csweb
/* * 使用經典的異步編程模型(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.xamlexpress
<Page x:Class="XamlDemo.Thread.Async.ClassicAsyncDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Thread.Async" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsg" FontSize="14.667" /> <Button Name="btnIAsyncResult" Content="IAsyncResult 的 Demo" Click="btnIAsyncResult_Click_1" Margin="0 10 0 0" /> </StackPanel> </Grid> </Page>
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); } } }
二、演示如何經過最新的異步編程模型(async 和 await)來進行異步操做
Thread/Async/NewAsyncDemo.xamlwindows
<Page x:Class="XamlDemo.Thread.Async.NewAsyncDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Thread.Async" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsg" FontSize="14.667" /> <Button Name="btnTaskWithoutReturn" Content="執行一個不帶返回值的 Task" Click="btnTaskWithoutReturn_Click_1" Margin="0 10 0 0" /> <Button Name="btnTaskWithReturn" Content="執行一個帶返回值的 Task" Click="btnTaskWithReturn_Click_1" Margin="0 10 0 0" /> <Button Name="btnMultiTask" Content="並行執行多個 Task" Click="btnMultiTask_Click_1" Margin="0 10 0 0" /> <Button Name="btnTaskWithoutAwait" Content="執行一個不 await 的 Task" Click="btnTaskWithoutAwait_Click_1" Margin="0 10 0 0" /> </StackPanel> </Grid> </Page>
Thread/Async/NewAsyncDemo.xaml.cs多線程
/* * 演示如何經過最新的異步編程模型(async 和 await)來進行異步操做 * * 注: * 一、要想 await,其所在方法必須標記爲 async * 二、方法被標記爲 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<int> 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(); } } }
三、演示如何將 IAsyncInfo(IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress) 轉成 Task
Thread/Async/IAsyncInfo2Task.xamlapp
<Page x:Class="XamlDemo.Thread.Async.IAsyncInfo2Task" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Thread.Async" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsg" FontSize="14.667" /> </StackPanel> </Grid> </Page>
Thread/Async/IAsyncInfo2Task.xaml.csasp.net
/* * 演示如何將 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<int> action = AsyncInfo.Run<int>( (token) => Task.Run<int>( () => { token.WaitHandle.WaitOne(3000); token.ThrowIfCancellationRequested(); return 10 * 10; }, token)); lblMsg.Text = "開始執行,3 秒後完成"; // 將 IAsyncOperation 轉換成 Task // AsTask() 是擴展方法,其邏輯在 System.WindowsRuntimeSystemExtensions 類中 Task<int> task = action.AsTask<int>(cts.Token); int result = await task; lblMsg.Text = "結果:" + result.ToString(); } } }
四、演示如何將 Task 轉成 IAsyncInfo(IAsyncAction, IAsyncOperation)
Thread/Async/Task2IAsyncInfo.xaml異步
<Page x:Class="XamlDemo.Thread.Async.Task2IAsyncInfo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Thread.Async" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsg" FontSize="14.667" /> </StackPanel> </Grid> </Page>
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<int> task = Task.Run<int>( () => { cts.Token.WaitHandle.WaitOne(3000); cts.Token.ThrowIfCancellationRequested(); return 10 * 10; }, cts.Token); lblMsg.Text = "開始執行,3 秒後完成"; // 將 Task 轉換成 IAsyncOperation // AsAsyncAction(), AsAsyncOperation() 是擴展方法,其邏輯在 System.WindowsRuntimeSystemExtensions 類中 IAsyncOperation<int> operation = task.AsAsyncOperation<int>(); int result = await operation; lblMsg.Text = "結果:" + result.ToString(); } } }
OK
[源碼下載]