简体   繁体   English

异步/等待vs线程方案

[英]Async/Await vs Threads Scenario

I'm new to C# and was wondering in which cases to use Async/Await and when to use threads as I understand that Async/Await do not create new threads. 我是C#的新手,我想知道在哪种情况下使用Async / Await以及何时使用线程,因为我了解Async / Await不会创建新线程。

For example, which of the two print methods below should be used if I want to schedule print hello every hour for the next ten hours? 例如,如果我想在接下来的十个小时中每小时安排一次打印问候,则应使用以下两种打印方法中的哪一种?

    private async void PrintHelloAsync(int delay)
    {
        await Task.Delay(delay);
        Console.WriteLine("Hello");
    }

    private void PrintHelloThread(int delay)
    {
        Task.Run(async () =>
        {
            await Task.Delay(delay);
            Console.WriteLine("Hello");
        });
    }

Should I call PrintHelloAsync 10 times with increasing delays, or PrintHelloThread? 我应该以增加的延迟调用10次PrintHelloAsync还是PrintHelloThread?

Am I even using these concurrency concepts correctly? 我什至正确使用了这些并发概念?

Right now I'm working on a project where I need to schedule a task at 6PM, 9PM, and Midnight and was trying to figure out the best way to do it. 现在,我正在一个项目中,我需要在6 PM、9PM和Midnight安排任务,并试图找出最好的方法。

The main difference between the two functions is that the first one is performed by the calling thread, while the second one is called by a free thread in the thread pool. 这两个函数之间的主要区别在于,第一个函数是由调用线程执行的,而第二个函数是由线程池中的空闲线程调用的。

Someone on stackoverflow explained me once the difference using the metaphor (Alas I don't know his name anymore). 有人用stackoverflow向我解释了一次隐喻的区别(可惜我不知道他的名字了)。

Suppose you want to make breakfast. 假设你想做早餐。 You need to toast some bread and boil some eggs. 您需要烤面包和煮鸡蛋。

You could put some bread in the toaster, wait until the bread is toasted, remove the toasted bread from the toaster and start boiling water. 您可以在烤面包机中放一些面包,等到烤面包为止,从烤面包机中取出烤面包,然后开水。 Once the water boils you add the eggs, wait some time and remove the eggs from the water and put out the fire. 水烧开后,您就可以添加鸡蛋了,请稍等片刻,然后从水中取出鸡蛋,然后将火熄灭。 This is a typical example of synchronous execution. 这是同步执行的典型示例。

On the other hand, after you put the bread in the toaster, you could already start boiling water. 另一方面,将面包放入烤面包机后,您可能已经开始沸腾水了。 Wait until either the bread is toasted or the water is boiling. 等到烤面包或水沸腾为止。 In the first case you'll remove the bread and wait for the water to boil. 在第一种情况下,您将取出面包,等待水沸腾。 In the latter case you'll put the eggs in the water and wait until either the bread is toasted or the eggs are ready. 在后一种情况下,您需要将鸡蛋放入水中,等到烤面包或鸡蛋准备好为止。 As soon as you have to await for something to happen you look around whether you can do something else to speed up the process: a typical example of asynchronous execution, but still performed by one thread. 一旦必须等待某些事情发生,就四处看看是否可以做其他事情来加快处理速度:这是异步执行的典型示例,但仍然由一个线程执行。 This is the method async-await uses, the method used by your first function. 这是async-await使用的方法,这是您的第一个函数使用的方法。

The most expensive method is hire a cook who you will order to toast some bread while you start heating the water to boil some eggs: concurrent processing performed by several threads. 最昂贵的方法是雇用一名厨师,当您开始加热水煮一些鸡蛋时,您将命令他烤些面包:由多个线程同时进行处理。

If you have a thread that has only one thing to do, it's not wise if that thread hires a cook to do the thing and let that thread wait until the cook is ready: why not let the thread do the thing? 如果您有一个仅做一件事的线程,那么如果该线程雇用一名厨师来做事情并让该线程等待直到厨师准备好,那是不明智的:为什么不让该线程去做事情呢?

So if your thread has nothing else to do, use your first function. 因此,如果您的线程无事可做,请使用第一个函数。

However this first function can only be called if your thread is running in an async function itself. 但是,仅当线程在异步函数本身中运行时才能调用第一个函数。 If your thread is not in an async function and it can do something meaningful while your bread is being toasted, consider using your second method. 如果线程不在异步函数中,并且在烘烤面包时它可以做一些有意义的事情,请考虑使用第二种方法。

I assume that ultimately your goal is to schedule your tasks for 6PM, 9PM, etc. Without going into too much detail, you are probably heading down the wrong path (with delayed tasks and thinking about threads). 我认为最终的目标是将任务安排在下午6点,下午9点等位置。在不做过多详细说明的情况下,您可能会走错路(延迟任务并考虑线程问题)。 Instead, I would recommend looking at a scheduler system - like Quartz.net or HangFire - hosted within a windows service, or simply using the windows task scheduler to start your application up at a specific time. 相反,我建议您查看Windows服务中托管的调度程序系统(例如Quartz.netHangFire) ,或者仅使用Windows任务调度程序在特定时间启动应用程序。

If you have no choice but to implement a scheduling system yourself, I would look at the System.Timers.Timer class as a start: 如果您别无选择,只能自己实现调度系统,那么我将以System.Timers.Timer类作为起点:

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

class Example
{
    static void Main()
    {
        Timer timer = new Timer(1000);
        timer.Elapsed += async ( sender, e ) => await HandleTimer();
        timer.Start();
        Console.Write("Press any key to exit... ");
        Console.ReadKey();
    }

    private static Task HandleTimer()
    {
        Console.WriteLine("Timer event");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM