【问题标题】:Is this code synchronous or asynchronous?这段代码是同步的还是异步的?
【发布时间】:2017-07-24 04:12:07
【问题描述】:

下面我尝试学习Task类的代码。从输出中,我看到主线程和任务线程同时运行。但我在异步方法中收到警告消息:

"警告 1 此异步方法缺少 'await' 运算符,将同步运行。考虑使用 'await' 运算符等待非阻塞 API 调用,或使用 'await Task.Run(...)' 来执行 CPU-在后台线程上绑定工作。”

那么下面的代码是同步的吗?

namespace SampleThreadTaskClass
{
    class Program
    {
        static void Main(string[] args)
        {           
            Task task = new Task(ProcessDataAsync);
            task.Start();

            Console.WriteLine("Enter any key");

            string input = Console.ReadLine();
            Console.WriteLine("You entered: " + input);

            Console.ReadLine(); 
        }

        static async void ProcessDataAsync()
        {
            for (int i = 0; i < 20; i++)
            {
                Thread.Sleep(500);
                Console.WriteLine("processing... " + i);
            }
        }
    }
}

【问题讨论】:

  • 我怀疑你误解了async。这并不意味着“使这个同步方法异步”。这意味着允许我在这个异步方法中使用异步等待。该方法必须是已经异步的。与await 类似。它不会使其参数异步;它标识了异步工作流中的一个点,在该点工作必须在工作流继续之前完成。
  • 是的,你是对的。我误解了这些概念。我想在创建 Task 对象并启动任务后,它会像后台工作线程一样独立运行另一个线程。
  • 此外,尝试了解控制台应用程序中的异步是一种非常令人困惑的开始方式。控制台不像 GUI 应用程序那样自然是异步的。尝试在 WPF 或 Winforms 应用中学习。

标签: c# multithreading asynchronous


【解决方案1】:

ProcessDataAsync 方法确实是同步的。它声称是异步的而且它就是在那个声称中

然后,您将 同步 方法提供给 Task 的构造函数,它将在线程池线程中执行该 同步 方法(您不应该由方式;如果你想在线程池线程中执行同步方法,你应该使用Task.Run)。

当然,对于您的情况,您想在线程池线程中执行此方法。你的异步操作只是在等待。没有必要安排一个新的线程池线程一次只坐在那里什么都不做。

你应该让ProcessDataAsync实际上是异步的,使用Task.Delay创建一个将在给定时间间隔内完成的Task,你可以await,然后你可以简单地调用ProcessDataAsync你想启动你的异步方法,它实际上是异步的

【讨论】:

  • 感谢您的深入解释。
【解决方案2】:

您应该尝试在启动任务之前编写一些代码,然后以异步方法启动任务。然后在第一个异步方法中使用另一个异步方法,例如 ProcessDataAsync 使用 await 运算符。这样您就可以了解异步行为。

这会有所帮助

static async Task ProcessDataAsync()
    {
        for (int i = 0; i < 20; i++)
        {
            await Task.Delay(500);
            Console.WriteLine("processing... " + i);
        }
    }

当您将返回类型更改为async 时,您需要将对ProcessDataAsyc 的调用更改为此

 var task = Task.Run(ProcessDataAsync);

是的,您的代码是异步的。

【讨论】:

  • 这个方法不应该是async void,调用代码需要修改。
  • 是的,我同意它应该返回Task。我只是保留它void,因为问题是这样的。 void 应该只在事件处理的情况下使用。
  • 谢谢。遵循 Alexander Sverla 的代码和链接后,我现在明白了。
  • blog.stephencleary.com/2012/02/async-and-await.html 这是关于异步和等待的最好的文章之一。仔细阅读它以获得更多理解。
【解决方案3】:

是的。 Thread.Sleep() 不是异步的。

见说明:https://msdn.microsoft.com/en-us/library/hh156528.aspx#Example

尝试延迟,然后你可以在它前面添加一个等待,

await Task.Delay(10000); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-15
    • 2020-02-21
    • 2013-02-25
    • 2012-12-30
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    相关资源
    最近更新 更多