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任务的构造函数是从基于任务的并行性中断的,不应该用在异步代码中.它只能用于创建基于代码的任务,而不是外部事件任务.

So,given the constraint that you cannot call any existing asynchronous methods and must complete both the Thread.Sleep and the Console.WriteLine in an asynchronous task,how do you do it in a manner that is as efficient as the original code?

我会使用某种类型的计时器,并使其完成taskcompletionsource< T>定时器触发.我几乎是积极的,这是实际的Task.Delay实现.

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...