无限循环的异步方法调用

时间:2016-10-24 15:45:23

标签: c# multithreading asynchronous async-await

我必须处理文件的Gb并使用具有异步方法的库将它们发送到网络以执行此类操作。

如果我执行以下操作,我认为如果需要一段时间才能完成,我将获得一个无限的线程编号:

void ProcessFiles()
{
    string[] files = /*a lot of files */

    foreach(file in files)
    {
        MyAsyncMethod(file)
    }
}

async void MyAsyncMethod(string file)
{
    string conent = File.ReadAllBytes(file);
    await MyLibrary.Async(call)
}

当然它应该是运行的并发线程数量的限制,但是会创建多个线程并且性能会变差...这应该是创建线程的限制...当达到此限制时会发生什么?新线程将在当前结束后创建?会被忽略吗?该程序将抛出异​​常??

如何管理这种“无限”的异步调用。我应该将其转换为同步调用(Task.start()+ Task.wait())并通过我自己的线程池进行管理吗?

谢谢

3 个答案:

答案 0 :(得分:0)

你不必担心线程,.NET会为你担心它们。

顺便提一下,您提供的代码是异步的,但按顺序运行:

foreach(string file in files)
{
    byte[] content = File.ReadAllBytes(file);
    await MyLibrary.AsyncCall(content); //<-- Loop is blocked per this await.
}

如果要实现并行性,则应考虑使用Task.WhenAllTask.WaitAll

在您的具体情况下,似乎MyLibrary.AsyncCall没有结果,因此您可以使用Task.WaitAll

Task[] tasks = files.Select(File.ReadAllBytes).Select(c => MyLibrary.AsyncCall(c)).ToArray();
Task.WaitAll(tasks); //<-- Will execute concurrently, and get back when they are all done.

至于问题&#34; Task.WaitAll是否为每个Task创建新主题?&#34;,答案是。 (Does the user of async/await create a new thread?

答案 1 :(得分:0)

上面的代码最多会使用一个线程,而不是您正在使用的线程。 “await”将要求系统进行任务调度,然后在任务完成时返回循环。如果任务实际上在相同或另一个线程上运行,那么你不能指望它。

如果要并行执行调用,从而利用多个线程(许多CPU内核),则应使用Parallel.For。请记住,在不确切知道如何操作的情况下,不应混合线程和异步。

答案 2 :(得分:0)

  1. 如果调用确实需要一个线程,系统将为您管理线程池,而不是产生无限的线程。

  2. 在许多情况下,there is no thread。异步不是多线程的同义词。多线程是 技术,用于异步执行任务,但这不是唯一的方法。