了解await& amp; async vs Task.Run [英] Understanding await & async vs Task.Run

查看:78
本文介绍了了解await& amp; async vs Task.Run的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,

希望你一切都好。我试图了解在C#中使用await和async关键字的兴趣,但即使我发现了很多(可能更多)文章,我仍然无法理解什么是兴趣......我更熟悉任务创建和任务
continuation。

Hope you're all fine. I'm trying to understand interest of using await and async keywords in C#but even I found a lot (probably more) of articles, I'll still unable to understand what is the interest ... I'm more familiar with task creation and task continuation.

这是我创建的自定义类的示例。此类将以异步方式从数据库导入项目列表(例如,包含IP地址),并为每个项目启动新任务以测试ping的连接。序列每1分钟执行
,并在需要时等待上一个序列完成。在下面的例子中,你能解释一下使用await& amp; async?

Here is an example of a custom class I created. This class will import a list of items (that contain IP address for example) from a database asynchronously and start a new task for each one to test connectivity from a ping. The sequence is executed every 1 minute and wait the previous sequence to be completed if needed. In the following example, can you explain me what would be the interest of using await & async ?

我不能把我的完整代码作为一个大项目的一部分,所以请随时告诉我你是否需要我做一些精确的事情。

I cannot put my full code as it's a part of a big project so feel free to tell me if you need me to precise a few things.

提前感谢您的帮助?

    public class Monitor
    {
        public List<MyMonitoring> MonitoredItems { get; set; }
        public Task[] PingTasks { get; set; }
        public Dictionary<MyWatcher, bool?> Results { get; set; }
        public int SequenceID { get; set; }
        public IServer Server { get; set; } = new Server();
        public System.Timers.Timer Timer { get; } = new System.Timers.Timer(60 * 1000 * 1);
        public BaseItem.Collection<MyWatcher> Watchers { get; set; }

        public Monitor()
        {
            Watchers = BaseItem.Collection<MyWatcher>.CreateAndFillAsync(UpdateMode.Never, false); // Load items from database asynchronously
            Watchers.TaskFill.ContinueWith(task =>
            {
                Trace.TraceInformation("Loaded watchers list: {0} results", Watchers.Count);
                Results = Watchers.ToDictionary(w => w, w => (bool?)null);
                Timer.AutoReset = true;
                Timer.Elapsed += OnElapsed;
                Timer.Start();
                PingTasks = GetNewSequence();
            });
        }

        public Task[] GetNewSequence()
        {
            var tasks = new List<Task>();
            Trace.TraceInformation("Started new monitoring sequence (ID {0}) at {1}", ++SequenceID, DateTime.Now.ToShortDateString());
            foreach (var w in Watchers)
            {
                var task = Task.Factory.StartNew(() =>
                {
                    var ping = new Ping();
                    var host = new IPAddress(w.IP).ToString();
                    var reply = ping.Send(host);
                    Trace.TraceInformation("{0}: Ping to {1} = {2} (last reply = {3})", w.Name, host, reply.Status, w.LastReply);
                    var connected = reply.Status == IPStatus.Success;
                    if (!w.LastReply.HasValue || w.LastReply.HasValue && w.LastReply.Value != connected)
                    {
                        Trace.TraceInformation("{0}: Connectivity changed from {1} to {2}", w.Name, w.LastReply, connected);
                        MyMonitoring.FromWatcher(w, connected).Write();
                    }
                    w.LastReply = connected;
                    Trace.TraceInformation("{0}: new state = {1}", w.Name, connected);
                });
            }
            return tasks.ToArray();
        }


        public void OnElapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (PingTasks != null)
            {
                Task.WaitAll(PingTasks); // Wait previous sequence to be terminated before starting a new one
                Trace.TraceInformation("Ended sequence monitoring (ID {0}) at {1})", SequenceID, DateTime.Now.ToShortDateString());
            }
            PingTasks = GetNewSequence();
        }
    }

推荐答案

你好NicolasC,

Hello NicolasC,

在我看来,await& async和Task.Run是一回事。前面的关键字(async,await)附带C#5.0,用于更方便地编写异步代码。我创建了一个简单的示例 如下所示。

In my opinion, The await & async and Task.Run is the same thing. The former keywords(async,await) come with C# 5.0 and is designed for writing asynchronous code more conveniently. I created a simple example as below.

 public class MyClass
    {
        public MyClass()
        {
            DisplayValue(); 
            Console.WriteLine("MyClass() End.");
        }
        public Task<double> GetValueAsync(double num1, double num2)
        {
            return Task.Run(() =>
            {
                for (int i = 0; i < 1000; i++)
                {
                    num1 = num1 / num2;
                    Thread.Sleep(1);
                }
                return num1;
            });
        }
        public async void DisplayValue()
        {
            double result = await GetValueAsync(1234.5, 1.01);

            Console.WriteLine("Value is : " + result);
        }
   }

当你调用上面的代码时,结果将显示如下。

When you invoke the above code, the result will display as below.

MyClass()结束。

值是:0.0589002735288036

你会发现异步方法(DisplayValue)  doesn' t阻止构造函数执行。在"DisplayValue"中方法,你会看到"等待"关键字,当主线程运行到那里时,它会立即返回。任务
将被传递到另一个线程来执行。后续代码为"等待"在"DisplayValue"中方法将等待任务完成执行。它就像Task对象的continue方法一样。

You will find the asynchronous method (DisplayValue) doesn't block the constructor executing. In the "DisplayValue" method, you will see the "await" keyword, when main thread run to there it will return immediately. The task will be delivered to another thread to execute. The behind code of "await" in "DisplayValue" method will wait the task finish executing. It just like the continue method of Task object.

实际上是"DisplayValue"。方法 运行如下。

Actually the "DisplayValue" method run as below.

public void DisplayValue()  
{  
    System.Runtime.CompilerServices.TaskAwaiter<double> awaiter = GetValueAsync(1234.5, 1.01).GetAwaiter();  
    awaiter.OnCompleted(() =>  
        {  
            double result = awaiter.GetResult();  
            System.Diagnostics.Debug.WriteLine("Value is : " + result);  
        });  
}   

因此,如果您将代码转换为使用  Async& Await,则代码应如下所示。

So if you convert your code to use Async&Await, the code should be like as below.

        public async void Monitor()
        {
             Watchers = await BaseItem.Collection<MyWatcher>.CreateAndFillAsync(UpdateMode.Never, false); // Load items from database asynchronously 
            ...
             Trace.TraceInformation("Loaded watchers list: {0} results", Watchers.Count);
             Results = Watchers.ToDictionary(w => w, w => (bool?)null);
             Timer.AutoReset = true;
             Timer.Elapsed += OnElapsed;
             Timer.Start();
             PingTasks = GetNewSequence();
            ...
        }

有一个关于异步程序的官方文档,你可以参考它。

There is a official document about asynchronous program, you could take reference with it.

https://docs.microsoft.com/en-us/dotnet/csharp/async

祝你好运,

Neil Hu


这篇关于了解await&amp; amp; async vs Task.Run的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆