重庆熊猫 Loading

.NET中如何在同步代码块中调用异步方法

更新记录
本文迁移自Panda666原博客,原发布时间:2021年7月2日。

在同步代码块中调用异步方法,方法有很多。

一、对于有返回值的Task

在同步代码块中直接访问 Task 的 Result 属性,这会阻塞调用线程直到返回Result为止。

代码实例:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace PandaTestClass
{
    class Program
    {
        private static async Task<(string, string)> DoSomething()
        {
            //用于返回值
            (string, string) result = ("?", "?");

            //任务1
            await Task.Run(() => {
                //模拟耗时任务
                for (int i = 0; i <= 100; i += 20)
                {
                    Console.WriteLine($"任务1,当前执行到:{i}%");
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                }
                //写入返回值
                result.Item1 = "任务1完成";
            });

            //任务2
            await Task.Run(() => {
                //模拟耗时任务
                for (int i = 0; i <= 100; i += 20)
                {
                    Console.WriteLine($"任务2,当前执行到:{i}%");
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                }
                //写入返回值
                result.Item2 = "任务2完成";
            });

            //确保任务执行完成
            Task.WaitAll(new Task[] { });
            //返回返回值
            return result;
        }

        static void Main(string[] args)
        {
            //同步块中使用异步方法
            //这里会阻塞主线程
            (string t1, string t2) result = DoSomething().Result;
            //执行完成
            Console.WriteLine("DoSomething Success");
            //获得结果集1
            Console.WriteLine(result.t1);
            //获得结果集2
            Console.WriteLine(result.t2);

            //wait
            Console.WriteLine("Main Suceess");
            Console.ReadKey();
        }
    }
}

二、使用Task.Run()方法包裹

强烈推荐该方法。

代码实例:

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace PandaTestClass
{
    class Program
    {
        /// <summary>
        /// 异步方法
        /// </summary>
        /// <returns></returns>
        private static async Task<(string, string)> DoSomething()
        {
            //用于返回值
            (string, string) result = ("?", "?");

            //任务1
            await Task.Run(() => {
                //模拟耗时任务
                for (int i = 0; i <= 100; i += 20)
                {
                    Console.WriteLine($"任务1,当前执行到:{i}%");
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                }

                //写入返回值
                result.Item1 = "任务1完成";
            });

            //任务2
            await Task.Run(() => {
                //模拟耗时任务
                for (int i = 0; i <= 100; i += 20)
                {
                    Console.WriteLine($"任务2,当前执行到:{i}%");
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                }

                //写入返回值
                result.Item2 = "任务2完成";
            });

            //确保任务执行完成
            Task.WaitAll(new Task[] { });
            //返回返回值
            return result;
        }

        static void Main(string[] args)
        {
            //同步块中使用异步方法
            //这里会阻塞主线程
            Task<(string t1, string t2)> returnValue = Task.Run(async () => {
                (string t1, string t2) r = await DoSomething();
                return r;
            });

            //执行完成
            //获得结果集1
            Console.WriteLine(returnValue.Result.t1);
            //获得结果集2
            Console.WriteLine(returnValue.Result.t2);

            //wait
            Console.WriteLine("Main Suceess");
            Console.ReadKey();
        }
    }
}
posted @ 2022-04-16 17:16  重庆熊猫  阅读(563)  评论(0编辑  收藏  举报