zoukankan      html  css  js  c++  java
  • 重新想象 Windows 8 Store Apps (44)

    [源码下载]


    重新想象 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

    <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);
            }
        }
    }


    2、演示如何通过最新的异步编程模型(async 和 await)来进行异步操作
    Thread/Async/NewAsyncDemo.xaml

    <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)来进行异步操作
     * 
     * 注:
     * 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<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();
            }
        }
    }


    3、演示如何将 IAsyncInfo(IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress) 转成 Task
    Thread/Async/IAsyncInfo2Task.xaml

    <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.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<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();
            }
        }
    }


    4、演示如何将 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
    [源码下载]

  • 相关阅读:
    Best Practices for Background Jobs_3 Managing Device Awake State之电源锁、Alarm、WakefulBroadcastReceiver
    一种扩大View点击范围的方法
    IntentService
    DNS
    GPU硬件加速相关
    SOA 面向服务的体系结构
    android APK 文件的生成过程
    PHP简介
    代码安装apk文件
    View 的 focus 和 selected 状态, TabContainer实现
  • 原文地址:https://www.cnblogs.com/webabcd/p/3204637.html
Copyright © 2011-2022 走看看