【问题标题】:Asynchronous Programming and await in a loop异步编程和循环等待
【发布时间】:2013-01-01 03:28:35
【问题描述】:

我开始学习 C# 5 和 .Net 4.5 中的异步编程,但有些东西我不明白。

private static int count;

public static void Main()
{
    LoopTest();

    Console.ReadKey(false);
}

static async void LoopTest()
{
    count = 0;

    for (var index = 0; index < 10; ++index)
    {
        Console.WriteLine( "({0}) In Loop before await, Index {1}, Thread: {2}", count++, index, Thread.CurrentThread.ManagedThreadId);
        await Task.Factory.StartNew(() => Thread.Sleep(10));
    }
}

结果是:

 (0) In Loop before await, Index 0, Thread: 9  
 (1) In Loop before await, Index 1, Thread: 10    
 (2) In Loop before await, Index 2, Thread: 11   
 (3) In Loop before await, Index 3, Thread: 10  
 (4) In Loop before await, Index 4, Thread: 11  
 (5) In Loop before await, Index 5, Thread: 10  
 (6) In Loop before await, Index 6, Thread: 12  
 (7) In Loop before await, Index 7, Thread: 11  
 (8) In Loop before await, Index 8, Thread: 10  
 (9) In Loop before await, Index 9, Thread: 12

那么是否有不同的线程访问同一个循环?索引变量是否存在 Race-Condition?

【问题讨论】:

  • 请替换 await Task.Factory.StartNew(() => Thread.Sleep(10));等待 Task.Delay(10)。你应该放开你的线程 10 毫秒,而不是坚持下去。
  • @publicENEMY Task.Delay 也是如此;)
  • @ToniPetrina Thread.Sleep 用于保持线程以模拟 10 毫秒的线程使用情况。

标签: c# .net multithreading asynchronous async-await


【解决方案1】:

不,没有竞争条件。您启动了一项新任务,该任务将在后台运行,但您的代码在该任务完成之前不会继续执行,因此您可以确保您的代码在任何时候都只会在一个线程中执行。

但是,因为这是一个控制台应用程序,所以没有当前的SyncronizationContext。 (与将存在的 winform、WPF、ASP、Silverlight 等应用程序相反。)这意味着来自任何 await 调用的延续将在线程池中运行,而不是在调用线程中。所以是的,您在循环的每次迭代中都在其中一个线程池线程中运行,并且每次都可能是不同的,但是您可以确定,除了您在新任务中放入的任何内容之外,您将“在开始处理下一个线程之前,在任何给定线程上运行“完成”,这确保在任何给定时间只有一个线程在运行代码(这意味着没有竞争条件)。

【讨论】:

  • 感谢您的回答!我明白了:)
【解决方案2】:

你所做的并不是真正的异步

await Task.Factory.StartNew(() => Thread.Sleep(10));

这会创建一个任务,然后等待该任务完成。你也可以在这里调用 Thread.Sleep(10)。

更合适的方法是:

Task myTask = Task.Factory.StartNew(() => Thread.Sleep(10));
... do stuff here ...
await myTask; // Now wait for the task to complete

如果您想在一个循环中执行多个任务,您应该查看Parallel.Foreach() 方法。

【讨论】:

  • 感谢您的回答!但我有几个问题。如果我在当前线程上创建任务,那么谁在创建其余线程?或者为什么 ManagedThreadId 不断变化?
  • 这个例子只是一个玩具例子,他正在试验并试图解释结果。这并不能解释这些结果,而是试图说测试是错误的,而实际上除了解释 await 的工作原理之外,它还没有尝试完成任何事情。
  • 对不起,我从答案中删除了我错误的“在当前线程上”短语。这些任务在线程池中运行,不一定会创建与您的任务一样多的线程。它将尝试为您管理资源,这是使用它优于线程的优势之一。
猜你喜欢
  • 2017-12-12
  • 1970-01-01
  • 2021-04-15
  • 1970-01-01
  • 2019-07-02
  • 2021-10-18
  • 2021-07-17
  • 1970-01-01
  • 2021-09-09
相关资源
最近更新 更多