C#中异步迭代IAsyncEnumerable应用的实现方法

发布时间:2021-06-28 11:46:27 作者:小新
来源:亿速云 阅读:550

小编给大家分享一下C#中异步迭代IAsyncEnumerable应用的实现方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

首先,尝试写第一个方法

private  void Button_Click(object sender, RoutedEventArgs e)
        {
            var dateStart = DateTime.Now;  //记录用时的起始时间
            DebugText = string.Empty;
            List<string> fpList = new List<string>() { "a", "b", "c", "d" };

            foreach (var item in MockIO)
            {
                var dateEnd = DateTime.Now;
                var timeSpan = dateEnd - dateStart;//记录开票用时
                DebugText += item + " " + timeSpan.TotalSeconds + "\r\n";

            }
        }

     /// <summary>
        /// 批量开票方法
        /// </summary>
        /// <param name="ls"></param>
        /// <returns></returns>
        public static IEnumerable<string> MockIO(List<string> ls)
        {

            foreach (var item in ls)
            {
                Task.Delay(1000).Wait();
                yield return item;
                Debug.WriteLine(Thread.GetCurrentProcessorId());
            }
        }

来看效果

C#中异步迭代IAsyncEnumerable应用的实现方法

很明显,发生了UI阻塞情况。因为我们并未对代码做任何异步处理。接下来,我们开始尝试修改。

首先,我们尝试按照常规异步方法修改 MockIO 函数,增加 async 关键词,返回结果增加 Task, 内部对IO操作添加 await。

修改完毕后,编译并没有通过,VS对该方法报异常

C#中异步迭代IAsyncEnumerable应用的实现方法

通过提示信息,我们可以发现,返回值 Task<IEnumerable<string>> 并不是可以迭代的,因为我们采用了 yield 来返回值,所以我们需要一个可以迭代的返回值。

比如改成这样

C#中异步迭代IAsyncEnumerable应用的实现方法

但是,这样一次就返回一组 Task ,没有用到方便的 yield;

此时,就可以用到 IAsyncEnumerable 来设计了,IAsyncEnumerable是C# 8.0引入的新特性,在异步迭代中,非常方便。如上述代码,可以直接修改为

public static async IAsyncEnumerable<string> MockIOAsync(List<string> ls)
        {
            foreach (var item in ls)
            {
                Task<Task<string>> task = Task<Task<string>>.Factory.StartNew(async () =>
               {
                   await Task.Delay(1000);
                   return item;

               });

                yield return await task.Result;
            }
        }

我们再运行调试,看一下效果

C#中异步迭代IAsyncEnumerable应用的实现方法

我们可以看到,不仅UI没有被阻塞,同时,传回的值也是一个接一个的传过来的,符合我们的预期。

扩展:虽然上述步骤我们完成的UI的非阻塞的实现,但是我们整个开票用时并没有节省。

接下来,我将继续修改 MockIOAsync 方法,将实现迭代器内部的多线程操作。

修改后的代码如下

public static async Task<IEnumerable<string>> MockIOPerformanceAsync(List<string> ls)
        {
            List<string> lss = new List<string>();
            List<Task> tasks = new List<Task>();
            foreach (var item in ls)
            {

                Task task = new Task(() =>
              {
                  Task.Delay(1000).Wait();
                  Debug.WriteLine(Thread.GetCurrentProcessorId());
                  lss.Add(item);
              });
                tasks.Add(task);
                task.Start();

            }
            foreach (var item in tasks)
            {
                await item;
            }
            return lss;
        }

效果展示:

C#中异步迭代IAsyncEnumerable应用的实现方法

嗯,速度很快,但是排序乱了,因为此方法在遍历中新建了线程,list 添加并不保证按照迭代器的顺序添加。

以上是“C#中异步迭代IAsyncEnumerable应用的实现方法”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

推荐阅读:
  1. C#实现异步编程的方法
  2. android应用中实现异步更新UI的方法有哪些

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

上一篇:Spring事件发布与监听机制的示例分析

下一篇:Java中线程通信及线程虚假唤醒的示例分析

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》