Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# AsParallel()或异步/等待_C#_.net_Asynchronous_Task Parallel Library_Async Await - Fatal编程技术网

C# AsParallel()或异步/等待

C# AsParallel()或异步/等待,c#,.net,asynchronous,task-parallel-library,async-await,C#,.net,Asynchronous,Task Parallel Library,Async Await,让我们假设执行一个方法CountString,给定一个字符串数组和一个int,返回长度大于该int的字符串数。 如果我必须尽可能地利用多核硬件,那么这样做是否足够: public int CountString(string[] s, int i) { return s.AsParallel().Count( res => res.length > i); } 或者我必须使用某种方式的任务,甚至混合任务和PLinq 这只是一个简单的例子,我知道这种方法对硬件性能影响不大 我想

让我们假设执行一个方法
CountString
,给定一个字符串数组和一个int,返回长度大于该int的字符串数。 如果我必须尽可能地利用多核硬件,那么这样做是否足够:

public int CountString(string[] s, int i) 
{
  return s.AsParallel().Count( res => res.length > i);
}
或者我必须使用某种方式的任务,甚至混合任务和PLinq

这只是一个简单的例子,我知道这种方法对硬件性能影响不大

我想知道这样做是否更好,使用
aspallel()
,或者在方法体中声明方法
async
并使用
wait
(即使我不知道如何做)。

编辑:

我看到你的实际问题有点误导,我会尝试回答有意的问题。特别是在这里,使用
AsParallel
将是一个很好的方法,因为实际上您不需要等待
任何东西。由于您正在处理一个集合,PLINQ或Paralle.ForEach是一个不错的选择。当你有自然的异步I/O绑定操作时,考虑使用<代码>异步等待> /代码>。建议不要这样做


如果您实际测试代码,您甚至可能会惊讶地发现,并行这段代码实际上会对方法执行产生负面的性能代价,这取决于您迭代的数组的大小

很多时候,人们忘记了使用线程实际上是有开销的,即使在线程池外使用线程也是如此。您必须进行最少的CPU密集型工作,这样才值得承受并行化带来的性能损失

如果数组足够长,那么使用
AsParallel
就足够了。没有理由添加
任务
,因为PLINQ可以很好地处理视差

好的,让我们实际测试一下这段代码。我将迭代一个填充了guid的
字符串[]
。代码如下:

主要方法:

void Main()
{
    //JIT
    Test(0);

    Test(100);
    Test(1000);
    Test(10000);
    Test(1000000);
    Test(10000000);
}

public void Test(int itemAmount)
{
    string[] strings = Enumerable.Range(0, itemAmount).Select(i => Guid.NewGuid()
                                                      .ToString()).ToArray();

    var stopWatch = Stopwatch.StartNew();
    CountStringInParallel(strings, itemAmount);
    stopWatch.Stop();
    Console.WriteLine("Parallel Call: String amount: {0}, Time: {1}", 
                                                        itemAmount, stopWatch.Elapsed);
    
    stopWatch.Restart();
    CountStringSync(strings, itemAmount);
    stopWatch.Stop();
    Console.WriteLine("Synchronous Call: String amount: {0}, Time: {1}", 
                                                        itemAmount, stopWatch.Elapsed);
}
并行和同步:

public int CountStringInParallel(string[] s, int i) 
{
    return s.AsParallel().Count( res => res.Length > i);
}

public int CountStringSync(string[] s, int i) 
{
    return s.Count(res => res.Length > i);
}
结果:

并行呼叫:字符串金额:100,时间:00:00:00.0000197

同步呼叫:字符串金额:100,时间:00:00:00.0000026


并行呼叫:字符串金额:1000,时间:00:00:00.0000266

同步呼叫:字符串金额:1000,时间:00:00:00.0000201


并行呼叫:字符串金额:10000,时间:00:00:00.0002060

同步呼叫:字符串金额:10000,时间:00:00:00.0002003


并行呼叫:字符串金额:1000000,时间:00:00:00.0080492

同步呼叫:字符串金额:1000000,时间:00:00:00.0135279


并行呼叫:字符串金额:10000000,时间:00:00:00.0744104

同步呼叫:字符串金额:10000000,时间:00:00:00.1402474


您可以看到多达10000个字符串,同步方法实际上比并行方法更快。

只要您不使用
异步等待
AsParallel
。没有理由直接使用任务,因为
aspallel
会在幕后为您完成任务

重要的是要记住,并行性有一个开销,在您的情况下,这个开销可能会大于并行性的附加值。为了使并行性真正提高性能,您应该处理许多项,并且工作本身应该是非常重要的

但是,如果需要,则需要使用
async wait
AsParallel
(以及PLinq的其余部分),因为它早于抽头。您需要使用
Task.Run
来并行处理和
Task.whalll
to
wait
。与此类似:

var tasks = items.Select(item => Task.Run(() => Process(item));
var results = await Task.WhenAll(tasks);
// process results

如果你没有非阻塞操作(也没有UI线程),你就不需要
任务
。请注意,你的工作太琐碎,无法从并行化中获益。是的,我知道,这只是一个纯粹的示例,必须主要考虑大量字符串来检查。。。顺便说一句,我要读那篇文章,谢谢!当然,这取决于
s
的长度。即使对于如此琐碎的工作负载,并行化也会带来好处,这肯定是一个临界点。为什么您认为OP的代码会有负面性能(假设
s
array很大而不是很小)?@YuvalItzchakov会有什么不同的解决方案?你能具体点吗;因为我想不起来one@YuvalItzchakov我猜你忽略了OP的密码。OP检查字符串数组中每个字符串的
Length
属性,而不是集合的计数。如果数组恰好很大,没有比OP所做的更好的方法了。@Sanci这取决于具体情况。当您在管道或生产者-消费者模式中进行处理时,查看TPL数据流会很有帮助。当您进行IO绑定操作时,
async wait
。当你有收藏时,你可以选择感觉更好的,你可以选择
PLINQ
Parallel.ForEach
。我的问题可能写得不好。我想问的是,将该方法声明为async并在方法中使用(我不知道如何使用)“await”是否更好,还是像我那样使用AsParallel()@Sanci,只要其中没有真正的异步(通常是I/O),那么使用async await就没有意义。