zoukankan      html  css  js  c++  java
  • 与WinRT组件进行操作

    1,原理:

    WinRT是一个新的类库,应用程序可以用它访问操作系统的功能.

    在内部,WinRT以组件的形式实现.COM Component Object Model…

    WinRT使用.net元数据来描述其API


    当C#引用COM对象的时候,实际上是获得一个RCW引用,该引用内部引用WINRT组件

    类似,将一个CLR对象传递给 WINRT API 实际上时将 CCW引用传递(com callerable Wrapper)

    2,投射:====WinRT核心概念

    文件名和命名空间: .winmd文件本身的名称必须和包含winrt组件的命名空间匹配. 比如,MyRT.PLC.winmd 文件必须在 MyRT.PLC命名空间或者其子命名空间定义RT组件.

    通用基类型.

    RT组件不共用基类.CLR投射的时候,感觉像从Object派生

    核心数据类型....bool 整数,浮点数,16位字符,字符串和void.


    类:支持继承和多态,但是没有使用基本上.


    结构: 支持结构. clr进行了某些投射,比如Point,Rect,Size,TimeSpan

    可控结构: 将 Foundation.IReference<T>投射成Nullable<T>

    枚举: 枚举值作为int传递.有符号时离散型,无符号是标志值类型[flag]

    方法:不支持Ref,支持Out(不可以同时输入输出.相当于INOUT)

    属性:不支持有参属性和只读属性

    委托:只能为参数类型和返回类型指定WinRT组件. WinRT委托没有BeginInvoke和EndInvoke方法

    事件:

    public delegate void TypedEventHandler<TSender,TResult>(TSender sender,TResult args)
    EventHandler<T>


    异常:使用HREsult指明状态. CLR投射成异常状态.其HResult属性用来包含HResult值.

    字符串:WinRT系统不允许字符串为null.可以传递String.Empty给WinRT API.

    日期: Foundation.DateTime结构代表一个UTC时间. CLR将其投射成 DateTimeOffset结构.在实列中,其将UTC时间转换成本地时间,然相反,clr将其作为UTC时间传给WinRT API


    URI:WinRT只支持绝对URL

    IClosable/IDispose   RT对象映射称为 Dispose方法,注意.Close方法不能执行任何IO操作.所以.需要显示调用存储方法来存储数据.

    数组:支持一维0基数组

    集合:CLR使用CCW来包装集合. 会跨边界操作.

    •     IITerable<T>   IEnumerable<T>
    •     IVector<T>    IList<T>
    •    IVectorView<T> IReadOnlyList<T>
    • IMap<K,V>           IDictionary<TKey,TValue>
    • IMapView<K,V>     IReadOnlyDictionary<TKey,TValue>
    • IKeyValuePair<K,V>  KeyValuePair<TKey,TValue>


    框架投射

           1,从.NET代码中调用异步WinRTAPI  API所在模块地址.

    C:Program Files (x86)Windows Kits8.1ReferencesCommonConfigurationNeutralAnnotatedWindows.winnmd

    C:WindowsSysWOW64WinMetadataC:WindowsSystem32WinMetadata

      public static void WinRTAsyncIntro()
            {
                //Provides access to common locations that contain user content. 
                //This includes content from a user's local libraries (such as Documents, Pictures, Music, and Videos),
                //HomeGroup, removable devices, and media server devices.
                IAsyncOperation<StorageFile> asyncOp = KnownFolders.MusicLibrary.GetFileAsync("Song.mp3");//在音乐中查找一首歌.
                asyncOp.Completed = OpCompleted;
                Console.WriteLine("Operation...Completed!");
            }
    
            private static void OpCompleted(IAsyncOperation<StorageFile> asyncInfo, AsyncStatus asyncStatus)
            {
                switch (asyncStatus)
                {
                    case AsyncStatus.Completed:
                        Console.WriteLine("Completed!");
                        break;
                    case AsyncStatus.Canceled:
                        Console.WriteLine("Canceled");
                        break;
                    case AsyncStatus.Error:
                        Exception exception = asyncInfo.ErrorCode;//将异常转化成异常类.
                        Console.WriteLine("Error"+exception.HResult.ToString());
                        break;
                    default:
                        break;
    
                }
            }

    1该类是个异步操作函数,用来在公共文件夹的音乐库中查找一首歌

    2 注意,在函数结束后,线程还在运行(除非进程结束).

    3,当线程完成后,触发事件,调用完成函数

       在完成函数里面,进行处理:

               注意:没有出现显示的异常. 无论任何情况,都会调用完成函数,在完成函数里面处理3中情况

           1,正常完成: status=completed

            2,任务取消:status=canceled  //调用所有IAsyncXXX提供的Cancel方法.

           3,发生异常:status=error 并且  异常的ErrorCode包装成了一个异常类.在其HResult中存放了异常的HResult.

    4,在处理完毕所有情况后,调用IAsyncXXX.Close()方法进行资源的清理.


      2,注意接口关系

         基本接口:

     [GuidAttribute(54, 0, 0, 192, 0, 0, 0, 0, 0, 0, 70)]
        [SupportedOn(100794368, Platform.Windows)]
        [SupportedOn(100794368, Platform.WindowsPhone)]
        [Version(100794368)]
        public interface IAsyncInfo
        {
            [SupportedOn(100794368, Platform.Windows)]
            [SupportedOn(100794368, Platform.WindowsPhone)]
            void Cancel();
            [SupportedOn(100794368, Platform.Windows)]
            [SupportedOn(100794368, Platform.WindowsPhone)]
            void Close();
    
            [SupportedOn(100794368, Platform.Windows)]
            [SupportedOn(100794368, Platform.WindowsPhone)]
            Exception ErrorCode { get; }
            [SupportedOn(100794368, Platform.Windows)]
            [SupportedOn(100794368, Platform.WindowsPhone)]
            uint Id { get; }
            [SupportedOn(100794368, Platform.Windows)]
            [SupportedOn(100794368, Platform.WindowsPhone)]
            AsyncStatus Status { get; }
        }

           AsyncStatus

    [SupportedOn(100794368, Platform.Windows)]
        [SupportedOn(100794368, Platform.WindowsPhone)]
        [Version(100794368)]
        public enum AsyncStatus
        {
            Started = 0,
            Completed = 1,
            Canceled = 2,
            Error = 3
        }


    几个异步函数比较

    IAsyncAction----Task
    IAsyncActionWithProgress<TProgress>---带有过程回调
    IAsynOperation<Tresut>---带返回参数
    IA十一年Operation With Progress<Tresult,TProgress>---带过程回调,带返回参数的异步操作


      利用C#提供的async和await简化代码:

     public static async void WinRTAsyncIntroEasy()
            {
                try
                {
                    StorageFile storageFile = await KnownFolders.MusicLibrary.GetFileAsync("Song.mp3");
    //正常结果
                }
    //异常完成
                catch (OperationCanceledException) { Console.WriteLine("operation is canceled"); }
                catch(Exception e) { Console.WriteLine(e.HResult.ToString());  }
    
            }

    1,要添加引用system.Runtime.WindowsRuntime.dll.

    C:WindowsWinSxSmsil_system.runtime.windowsruntime_*

    2,注意该函数是一个异步函数. 但是在函数内部是同步的.使用await关键字的作用:

             1,如果没有await关键字,那么异步操作将导致 GetFileAsync...异步执行,将执行下面的语句.加入await后,函数在这里就返回了,当异步函数没有执行完毕前,其不会执行下面的语句.

             2,await进行了数据的转换, 比如    int t=Task<int> XXXAsync() 如果函数正确完成,那么就会将结果返回给t.

             3,await在返回后,才继续执行下面的语句.所以,上面的方法,是一个很不错的范式.

     public static async Task TryConnectPlcAsync(CancellationToken token)
            {
    
    
    
    
                Plc plc = new Plc(CpuType.Logo0BA8, "192.167.0.0", 0, 1);
    
                Task t1 = plc.OpenAsync();//一个PLC异步函数,注意,异步函数的异常只能通过await来接收,它并不会直接导致出错.只是会终止线程.
    
    
    
    
    
                Task t2 = Task.Run(() =>//一种将没有取消功能的异步函数增加取消功能.
                {
    
                    do
                    {
    
                        log("token is"+token.IsCancellationRequested.ToString());
                        log(t1.Status.ToString());
    
                        if (token.IsCancellationRequested)
                        {
                            //token.ThrowIfCancellationRequested();
                            throw new Exception();
                        }
                        if (t1.IsFaulted) throw t1.Exception;
    
                    } while (true);
    
                },token
                );
                try
                {
    
                    await t2;
                }
                catch(Exception e)
                {
                    log(e.Message+"in 1");
                    //throw;        有的时候,将throw 抛给上层,并且运行完finally之后,就返回.//没的时候,不抛给上层.
    
                }
    
                finally
                {
                    plc.Close();
                    Console.WriteLine("plc is closed");
                }
               //正常完成的情况.
    
                Console.WriteLine("ok...");
    
            }
            public static async Task TryConnectPLCTest()
            {
                var tokenSource = new CancellationTokenSource();
                var token = tokenSource.Token;
                Task t = TryConnectPlcAsync( token);
                Thread.Sleep(100);
                //tokenSource.Cancel();用于 给 toekn设定一个取消标志.然后交给异步程序进行处理.(向异步程序传递取消标志).
                try
                {
                    await t;//必须在这个地方捕捉错误,否则,异步任务的错误捕捉不到.
                    Console.WriteLine(t.Status);
                }
                catch(Exception e)
                {
                    log(e.GetType().ToString());
                }
                finally
                {
                    tokenSource.Dispose();
                }
            }

    注意1:  取消的用法:建立一个cancellationTokenSource对象,并且将其token传递给异步函数,当设定cancellationTokenSource.Cancel()方法的时候,就会向异步函数的token.IsCancelRequest传递true;

    注意2:在异步中发生的错误,需要 await Task 中进行捕捉,否则会捕捉不到

    注意3:使用一个包装来强制在取消的时候,抛出,任务取消异常.查看Task t2.

  • 相关阅读:
    npm安装Vue及配置
    Node.js安装
    代码优化总结
    Java 读取文件指定行数的数据
    Navicat Premium 15 v15.0.17 数据库开发工具 安装激活详解
    发现了一个关于 gin 1.3.0 框架的 bug
    802.1X 账号密码+设备信息双重认证
    Vue项目入门(一)
    WPF登录界面
    使用“user32.dll”控制窗体
  • 原文地址:https://www.cnblogs.com/frogkiller/p/12345311.html
Copyright © 2011-2022 走看看