List<string> myList = new List<string>();myList.AddRange(new MyClass1().Load());myList.AddRange(new MyClass2().Load());myList.AddRange(new MyClass3().Load());myList.DoSomethingWithValues();
什么是异步运行任意数量的Load()方法的最佳方法,然后确保在所有异步线程完成时运行DoSomethingWithValues()(当然每次回调发生时都不会增加变量并等待== 3)
解决方法 Ani的概念解决方案可以更简洁地编写:new ILoadable[] { new MyClass1(),new MyClass2(),new MyClass3() } .AsParallel().SelectMany(o => o.Load()).ToList() .DoSomethingWithValues();
这是我的首选解决方案:声明式(AsParallel)和简洁.
当以这种方式编写时,Reed的解决方案如下所示:
new ILoadable[] { new MyClass1(),new MyClass3() } .Select(o=>Task.Factory.StartNew(()=>o.Load().ToArray())).ToArray() .SelectMany(t=>t.Result).ToList() .DoSomethingWithValues();
请注意,两个ToArray调用可能都是必要的.如果o.Load是懒惰的(通常它可以是YMMV),第一次调用是必要的,以确保在后台任务中完成o.Load的评估.第二次调用是必要的,以确保在调用SelectMany之前完全构造了任务列表 – 如果不这样做,那么SelectMany将尝试仅在必要时迭代其源 – 即它不会迭代到必须进行的第二项任务,直到计算出第一项任务的结果为止.实际上,您正在启动任务,但随后又一个接一个地执行它们 – 将后台任务转换回严格的顺序执行.
请注意,第二个声明性较小的解决方案存在更多陷阱,需要进行更彻底的分析以确保它是正确的 – 即,这样可维护性较差,但仍比手动线程更好.顺便说一句,您可以放弃对.ToList的调用 – 这取决于DoSomethingWithValues的细节 – 以获得更好的性能,从而您的最终处理可以访问第一个值,因为它们无需等待所有要完成的任务或并行枚举.这甚至更短!
总结以上是内存溢出为你收集整理的C#:异步运行此代码的不同方法?全部内容,希望文章能够帮你解决C#:异步运行此代码的不同方法?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)