• 2018-11-5-win10-uwp-异步转同步


    title author date CreateTime categories
    win10 uwp 异步转同步
    lindexi
    2018-11-05 10:18:40 +0800
    2018-2-13 17:23:3 +0800
    Win10 UWP

    有很多方法都是异步,那么如何从异步转到同步?

    在本文开始,我必须告诉大家,这个方法可能立即死锁,所以使用的时候需要满足下面的条件

    使用的条件

    1. 异步转同步的线程不是 UI 线程

    2. 如果线程是UI线程,那么异步方法不能在另外一个线程。

    看到这里也许你会疑惑,为何异步方法可以不在另一个线程?实际上对于 IO 等的异步方法,都是没有创建线程,请看There Is No Thread

    关于这条件是如何来的,请看使用 Task.Wait()?立刻死锁(deadlock) - walterlv

    使用方法

    可以使用的方法需要获得是否有返回值,返回值是否需要。

    如果需要返回值,使用GetResults

    如从文件夹获取文件:

                    StorageFolder folder = StorageFolder.GetFolderFromPathAsync("").GetResults();
    

    这是同步方法,几乎不需要做什么修改

    如果是没有返回值或不需要返回值的,请看下面代码

                    StorageFolder.GetFolderFromPathAsync("").AsTask().Wait();
    

    假设一个方法是没返回的,可以使用Wait

                Foo().Wait();
    
    
        private async Task Foo()

    通过这个方法就可以把异步方法转同步。

    如果需要反过来,把同步转异步,可以使用 同步方法转异步

                await Task.Run(() =>
                {
                   写你的代码
                });

    使用Task.Wait 时需要小心死锁

    不会出现死锁的代码

    直接在UI使用Task.Run

            private void Button_OnClick(object sender, RoutedEventArgs e)
            {
                var n = Task.Run(() =>
                  {
                      return 2;
                  }).Result;
            }

    使用Task.Delay等待

            private void Button_OnClick(object sender, RoutedEventArgs e)
            {
                Task.Delay(100).Wait();
            }
    

    即使使用方法,里面使用 io 也有可能死锁

            private void Button_OnClick(object sender, RoutedEventArgs e)
            {
                DoAsync().Wait();
            }
    
    
            private async Task DoAsync()
            {
                // 调用这个方法在 10.0.17134 / 10.0.16299 概率的死锁
                // 在 10.0.17763 基本就会死锁
                await ApplicationData.Current.LocalFolder.CreateFileAsync("lin", CreationCollisionOption.ReplaceExisting);
            }

    会出现死锁的写法

    在UI使用异步会创建线程的方法

            private void Button_OnClick(object sender, RoutedEventArgs e)
            {
                DoAsync().Wait();
            }
    
    
            async Task DoAsync()
            {
                await Task.Run(() => { });
            }
            private void Button_OnClick(object sender, RoutedEventArgs e)
            {
                DoAsync().Wait();
            }
    
    
            async Task DoAsync()
            {
                await Task.Delay(100);
            }
            private void Button_OnClick(object sender, RoutedEventArgs e)
            {
                DoAsync().Wait();
            }
    
    
    
            private async Task DoAsync()
            {
                await Task.Run( () =>
                {
                    ApplicationData.Current.LocalFolder.CreateFileAsync("123",
                        CreationCollisionOption.ReplaceExisting).GetResults();
                });
            }

    参见:使用 Task.Wait()?立刻死锁(deadlock) - walterlv

  • 相关阅读:
    python : 将txt文件中的数据读为numpy数组或列表
    ROS :为IDE配置环境变量
    ROS 教程之 navigation :在 catkin 环境下创建costmap layer plugin
    ROS 教程之 vision : 用各种摄像头获取图像
    ROS 教程之 network:多台计算机之间网络通信(2)
    MS sql 查询动态表名的方法
    把ocx打包成CAB,并签名
    DataSet 转换成List
    C# 反序列化datetime的处理
    PSP软件开发过程管理
  • 原文地址:https://www.cnblogs.com/lindexi/p/12086652.html
Copyright © 2020-2023  润新知