Tam*_*aky 10 c# multithreading async-await
为什么运行一百个异步任务比运行一百个线程需要更长的时间?
我有以下测试类:
public class AsyncTests
{
public void TestMethod1()
{
var tasks = new List<Task>();
for (var i = 0; i < 100; i++)
{
var task = new Task(Action);
tasks.Add(task);
task.Start();
}
Task.WaitAll(tasks.ToArray());
}
public void TestMethod2()
{
var threads = new List<Thread>();
for (var i = 0; i < 100; i++)
{
var thread = new Thread(Action);
threads.Add(thread);
thread.Start();
}
foreach (var thread in threads)
{
thread.Join();
}
}
private void Action()
{
var task1 = LongRunningOperationAsync();
var task2 = LongRunningOperationAsync();
var task3 = LongRunningOperationAsync();
var task4 = LongRunningOperationAsync();
var task5 = LongRunningOperationAsync();
Task[] tasks = {task1, task2, task3, task4, task5};
Task.WaitAll(tasks);
}
public async Task<int> LongRunningOperationAsync()
{
var sw = Stopwatch.StartNew();
await Task.Delay(500);
Debug.WriteLine("Completed at {0}, took {1}ms", DateTime.Now, sw.Elapsed.TotalMilliseconds);
return 1;
}
}
Run Code Online (Sandbox Code Playgroud)
至于所知道的,TestMethod1
和TestMethod2
应该做的完全一样的.一个使用TPL,两个使用普通的香草线程.一个需要1:30分钟,两个需要0.54秒.
为什么?
Luk*_*oid 12
该Action
方法目前正在使用阻止Task.WaitAll(tasks)
.Task
默认使用时,ThreadPool
将使用它来执行,这意味着您正在阻止共享ThreadPool
线程.
尝试以下操作,您将看到相同的性能:
添加一个非阻塞实现Action
,我们将其称之为ActionAsync
private Task ActionAsync()
{
var task1 = LongRunningOperationAsync();
var task2 = LongRunningOperationAsync();
var task3 = LongRunningOperationAsync();
var task4 = LongRunningOperationAsync();
var task5 = LongRunningOperationAsync();
Task[] tasks = {task1, task2, task3, task4, task5};
return Task.WhenAll(tasks);
}
Run Code Online (Sandbox Code Playgroud)修改TestMethod1
以正确处理新的Task
返回ActionAsync
方法
public void TestMethod1()
{
var tasks = new List<Task>();
for (var i = 0; i < 100; i++)
{
tasks.Add(Task.Run(new Func<Task>(ActionAsync)));
}
Task.WaitAll(tasks.ToArray());
}
Run Code Online (Sandbox Code Playgroud)你性能低下的原因是因为ThreadPool
如果需要的话,"慢慢"会产生新的线程,如果你阻塞它可用的几个线程,你会遇到明显的减速.这就是为什么ThreadPool
它仅用于运行短任务.
如果您打算使用长时间阻塞操作,Task
那么请确保TaskCreationOptions.LongRunning
在创建Task
实例时使用(这将创建一个新的底层Thread
而不是使用ThreadPool
).
进一步证明ThreadPool
存在问题,以下内容也可以缓解您的问题(请勿使用此问题):
ThreadPool.SetMinThreads(500, 500);
Run Code Online (Sandbox Code Playgroud)
这表明新ThreadPool
线程的"缓慢"产生导致了您的瓶颈.
归档时间: |
|
查看次数: |
957 次 |
最近记录: |