Task.Run 不像 Thread.start 那样工作

Azz*_*o94 5 c# multithreading task

我一直在开发一个应用程序,我需要以并行而不是阻塞的方式运行一些方法。首先我使用Task.Run,但在调试模式下,我看到操作阻塞并等待结果。我不想要这个,我想要在foreach 循环中调用的所有方法异步运行。

public async void f()
{
    foreach (var item in childrenANDparents)
    {
        await Task.Run(() => SendUpdatedSiteInfo(item.Host,site_fr));
        // foreach loop does not work until the task return and continues
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我将 task.run 更改为 thread.start并且效果很好!

public async void f()
{
    foreach (var item in childrenANDparents)
    {
        Thread t = new Thread(() => SendUpdatedSiteInfo(item.Host, site_fr));
        t.Start();
        // foreach loop  works regardless of the method, in debug mode it shows me 
        // they are working in parallel
    }
}
Run Code Online (Sandbox Code Playgroud)

你能解释一下有什么区别吗?为什么?我期望两个代码的行为相同,而且它们似乎不同。

谢谢

Fab*_*jan 7

我希望在 foreach 循环中调用的所有方法异步运行。

您似乎将 async/sync 调用与parallelization混淆了。

引用自 MSDN:

数据并行性:并行处理的一种形式,其中相同的计算在不同的数据上并行执行。Microsoft .NET Framework 中的 Parallel.For 和 Parallel.ForEach 方法以及 PLINQ 支持数据并行性。与任务并行性相比。

异步操作:在操作开始时不阻塞当前控制线程的操作。

让我们再仔细看看你的代码:

foreach (var item in childrenANDparents)
{
    await Task.Run(() => SendUpdatedSiteInfo(item.Host,site_fr));
}
Run Code Online (Sandbox Code Playgroud)

await 关键字将导致编译器创建一个 StateMachine 来处理方法执行。

就像你对编译器说:“在不阻塞任何线程的情况下启动这个异步操作,当它完成时 - 执行其余的东西”。

Task 完成执行后,该线程将被释放并返回到 ThreadPool,它将在 ThreadPool 中的第一个可用线程上执行其余代码,并尝试在已启动方法执行的线程中执行它(除非使用 .ConfigureAwait(false) 在这种情况下,当我们并不真正关心哪个线程将执行延续时,它更像是“即发即弃”模式)。

当你创建Thread一个单独的线程时,你通过委托一些代码在一个单独的线程中运行来实现并行。因此,根据代码本身,它可能会或可能不会异步执行。

就像你对编译器说:“拿这件工作开始一个新线程并在那里做”

如果您仍然想使用具有并行性的任务,您可以在循环中创建一个任务数组,然后等待所有任务完成执行:

var tasks = new[] 
{ 
    childrenANDparents.Select(item=> Task.Run(() => SendUpdatedSiteInfo(item.Host,site_fr)));
}

await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)

聚苯乙烯

是的,您也可以使用TPL(任务并行库),特别是并行循环。


AAA*_*ddd 4

你可以使用一个简单的Parallel.ForEachPLinq

Parallel.ForEach(childrenANDparents, (item) => 
                            {
                               SendUpdatedSiteInfo(item.Host,site_fr)
                            });
Run Code Online (Sandbox Code Playgroud)

为了更好地理解asyncawait最好开始阅读一些文档,这是一个很大的主题,但值得您花时间

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/