c# – 如何将其转换为异步任务?
给出以下代码…
static void DoSomething(int id) { Thread.Sleep(50); Console.WriteLine(@"DidSomething({0})",id); } 我知道我可以将它转换为异步任务,如下所示: static async Task DoSomethingAsync(int id) { await Task.Delay(50); Console.WriteLine(@"DidSomethingAsync({0})",id); } 而且,如果我多次呼叫(Task.WhenAll),所有这一切将比使用Parallel.Foreach甚至在循环中调用更快更有效率. 但是一会儿,假装Task.Delay()不存在,我实际上必须使用Thread.Sleep();我知道现实情况并非如此,但这是概念代码,延迟/睡眠通常是没有async选项(如早期EF)的IO操作. 我尝试过以下内容 static async Task DoSomethingAsync2(int id) { await Task.Run(() => { Thread.Sleep(50); Console.WriteLine(@"DidSomethingAsync({0})",id); }); } 但是,尽管它运行没有错误,根据Lucien Wischik,这实际上是不好的做法,因为它只是从池中旋转线程来完成每个任务(使用以下控制台应用程序也是较慢的 – 如果在DoSomethingAsync和DoSomethingAsync2调用之间进行交换您可以看到完成所需的时间有显着差异) static void Main(string[] args) { MainAsync(args).Wait(); } static async Task MainAsync(String[] args) { List<Task> tasks = new List<Task>(); for (int i = 1; i <= 1000; i++) tasks.Add(DoSomethingAsync2(i)); // Can replace with any version await Task.WhenAll(tasks); } 然后我尝试了以下内容 static async Task DoSomethingAsync3(int id) { await new Task(() => { Thread.Sleep(50); Console.WriteLine(@"DidSomethingAsync({0})",id); }); } 移植这个代替原来的DoSomethingAsync,测试从未完成,屏幕上没有显示任何内容! 我也尝试了多个其他变体,不编译或不完成! 所以,考虑到你不能调用任何现有的异步方法,并且必须在异步任务中完成Thread.Sleep和Console.WriteLine的约束,你如何以与原始代码一样的方式来执行它? 对于那些有兴趣的人来说,这个目标是让我更好地了解如何创建我自己的异步方法,我不会打电话给任何人.尽管有许多搜索,这似乎是一个真正缺少示例的领域 – 而且有数千个调用异步方法的例子可以调用其他异步方法,我无法找到将现有的void方法转换为异步任务的任何方法除了使用Task.Run(()=> {})方法之外,还没有调用进一步的异步任务. 解决方法
有两种任务:执行代码(例如Task.Run和朋友)以及响应某些外部事件(例如TaskCompletionSource&T和朋友)的任务.
您要查找的是TaskCompletionSource< T>.对于常见情况,有各种“速记”形式,因此您不必总是使用TaskCompletionSource< T>直.例如Task.FromResult或TaskFactory.FromAsync.如果您现有的* Begin / * End实现了I / O,则FromAsync最常用;否则,您可以使用TaskCompletionSource< T>直. 有关更多信息,请参阅Implementing the Task-based Asynchronous Pattern的“I / O绑定任务”部分. (不幸的是)Task任务的构造函数是从基于任务的并行性中断的,不应该用在异步代码中.它只能用于创建基于代码的任务,而不是外部事件任务.
我会使用某种类型的计时器,并使其完成TaskCompletionSource< T>定时器触发.我几乎是积极的,这是实际的Task.Delay实现. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |