如何使用异步和等待正确处理 [英] How to dispose properly using async and await

查看:118
本文介绍了如何使用异步和等待正确处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将代码从 Thread 替换为 Task 。睡眠/延迟只是代表长时间的活动。

I'm trying to make code replacement from Thread to Task. The sleep / delay is just representing long running activity.

static void Main(string[] args)
{
    ThreadDoWork();
    TaskDoWork();
}
public static void ThreadDoWork()
{
    using (var dispose = new ThreadDispose())
    {
        dispose.RunAsync();
    }
}
public static async void TaskDoWork()
{
    using (var dispose = new TaskDispose())
    {
        await dispose.RunAsync();
    }
}
public class ThreadDispose : IDisposable
{
    public void RunAsync ()
    {
        ThreadPool.QueueUserWorkItem(state =>
        {
            Thread.Sleep(3000);
        });
    }
    void IDisposable.Dispose()
    {
        File.AppendAllText("D:\\test.txt", "thread disposing");
    }
}
public class TaskDispose : IDisposable
{
    public async Task RunAsync()
    {
        await Task.Delay(3000);
    }
    void IDisposable.Dispose()
    {
        File.AppendAllText("D:\\test.txt", "task disposing");
    }
}

test.txt 只是


线程处理

thread disposing

我需要更改什么顺序 TaskDispose :: Dispose 总是像 ThreadDispose

What do I need to change in order TaskDispose::Dispose is always executed just like ThreadDispose?

推荐答案

让我们隔离每段代码:

public static void ThreadDoWork()
{
    using (var dispose = new ThreadDispose())
    { 
        dispose.RunAsync();
    }
}

public void RunAsync()
{
    ThreadPool.QueueUserWorkItem(state =>
    {
        Thread.Sleep(3000);
    });
}

在第一段代码中,您要做的是在线程池线程上进行队列工作。因为您是在 using 范围内运行此代码的,并且它在另一个线程上异步运行,所以它立即处理。这就是为什么您在文本文件中看到处理消息的原因。

What you do in this first piece of code is queue work on a threadpool thread. Because you're running this code inside a using scope and it runs asynchronously on a different thread, it disposes immediately. That is why you see the dispose message inside your text file.

public static async void TaskDoWork()
{
   using (var dispose = new TaskDispose())
   {
       await dispose.RunAsync();
   }
}

public class TaskDispose : IDisposable
{
   public async Task RunAsync()
   {
       await Task.Delay(3000);
   }
}

当您等待时在方法内部,您实际说的是类似以下内容的内容:"执行此代码。因为它本质上是异步的,所以我将控制权返回给调用方法,一旦完成异步操作,请回叫我。

When you await inside your method, what you actually say is something along the lines of: "Execute this code. Because it's asynchronous by nature, I will return control back to the calling method, please call me back once you complete the asynchronous operation".

您的代码命中了 await 关键字,并将控制权返回给您的 Main 方法。在 Main 内部,您的异步方法是要执行的最后一段代码,因此完成了您的应用程序,并且没有机会进行 Dispose 方法执行。

Your code hits the await keyword and returns control to your Main method. Inside Main, your async method is the last piece of code to execute, hence finishing your application, and not giving a chance for your Dispose method to execute.

如果要处理它,则必须将返回类型从 void 更改到 Task 并显式 Wait

If you want it to dispose, you'll have to change the return type from void to Task and explicitly Wait:

public static async Task TaskDoWork()
{
    using (var dispose = new TaskDispose())
    {
       await dispose.RunAsync();
    }
}

现在:

static void Main(string[] args)
{
    ThreadDoWork();
    TaskDoWork().Wait();
}

侧面注:

应遵循以下准则:


  1. async void 用于与事件处理程序兼容,很少有超出该范围的场合应使用它。而是使用 async Task

  1. async void is for compatability with event handlers, there are rarely occasions outside that scope where it should be used. Instead, use async Task.

使用TAP进行异步操作的方法(任务异步模式)应以异步后缀结尾。 TaskDoWork 应该为 TaskDoWorkAsync

Methods doing asynchoronous operation using TAP (Task Asynchronous Pattern) should end with the Async postfix. TaskDoWork should be TaskDoWorkAsync.

任务上使用 Wait 可能会导致死锁。在这种特殊情况下,这不是因为控制台应用程序没有 SynchronizationContext 并使用了线程池。推荐的方法是一路异步。并使用 await

Using Wait on a Task can cause deadlocks. In this particular case it doesn't because a console application doesn't have a SynchronizationContext and uses the threadpools. The recommended approach is to go "async all the way" and use await.

里面有很多阅读材料 async-await标签Wiki ,请确保将其签出。

There is great reading material inside the async-await tag wiki, make sure to check it out.

这篇关于如何使用异步和等待正确处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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