繁体   English   中英

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

[英]Task.Run does not work like Thread.start

我一直在开发一个应用程序,我需要运行一些方法作为并行而不是阻塞。 首先我使用了Task.Run ,但在IN DEBUG MODE中 ,我看到操作阻塞并等待结果。 我不想要这个,我想要在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
    }
}

所以我将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
    }
}

你能解释一下有什么区别和原因吗? 我希望两个代码都有相同的行为,看起来它们是不同的。

谢谢

您可以使用简单的Parallel.ForEachPLinq

Parallel.ForEach(childrenANDparents, (item) => 
                            {
                               SendUpdatedSiteInfo(item.Host,site_fr)
                            });

为了更好地理解asyncawait它最好开始阅读一些docos,这是一个很大的话题,但它值得您光顾

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

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

您似乎将混淆异步/同步调用与并行化混淆。

来自MSDN的引用:

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

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

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

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

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

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

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

当您创建单独的Thread您可以通过委派一些代码在单独的线程中运行来执行并行操作。 因此,根据代码本身,它可能会也可能不会异步执行。

就像你对编译器说的那样:“接受这项工作开始一个新的线程并在那里做”

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

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

await Task.WhenAll(tasks);

PS

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM