为什么这么慢,.net任务嵌套子任务
本文关键字:任务 嵌套 子任务 net 为什么 | 更新日期: 2023-09-27 18:16:39
我创建了一个asp.net webapi测试应用程序,下面是我的测试代码:
当我使用result = index.ToString() + this.getresult().Result;
时,响应时间为2s。如果我使用Thread.Sleep(100); result = index.ToString();
,它只需要200ms。
public class HomeController : Controller
{
public string Test()
{
var listName = new List<int>();
for (int i = 0; i < 100; i++)
{
listName.Add(i);
}
var response = Task.WhenAll(listName.Select(sendrequest)).Result;
return string.Join(",", response);
}
public async Task<string> sendrequest(int index)
{
return await Task.Factory.StartNew(() =>
{
string result = string.Empty;
try
{
Thread.Sleep(100); result = index.ToString();
//result = index.ToString() + this.getresult().Result;
}
catch (Exception ex)
{
System.IO.File.AppendAllText("D:''WebService''FelixTest''log.txt",ex.ToString());
}
return result;
}).ConfigureAwait(false);
}
public async Task<string> getresult()
{
await Task.Delay(100);
return "OK";
}
}
我认为你正在遭受ThreadPool
线程饥饿。问题出在你注释掉的那行
//result = index.ToString() + this.getresult().Result;
通过访问Task.Result
属性,您将在getresult()
方法返回的Task
上引起Wait
。Wait操作阻止当前线程执行,这意味着下一个Task必须安排在另一个线程上,依此类推。当您启动100个任务时,所有这些任务都将阻塞,ThreadPool将尝试启动新的托管线程来满足需求,这是一个耗时的过程。
我会重新组织你的代码,使一切都是异步的,除了一个顶级Test
方法。在这个例子中,我不确定为什么需要Task.Factory.StartNew()
,因为任务已经并行运行(至少部分),因为它们使用async-await模式。也许您的实际示例需要将任务安排在后台线程上?如果你不需要使用Factory.StartNew()
,我建议重写sendrequest
像这样:-
public async Task<string> sendrequest(int index)
{
string result = string.Empty;
try
{
result = index.ToString() + await this.getresult();
}
catch (Exception ex)
{
System.IO.File.AppendAllText("D:''WebService''FelixTest''log.txt",ex.ToString());
}
return result;
}
如果你确实需要使用Factory.StartNew()
,你仍然可以实现同样的事情,但是你传递给StartNew
的委托应该标记为async
。
根据您的描述,差值为1800毫秒。在getresult
中有100毫秒的延迟。如果我们减去这个,差是1700毫秒。与"OK"
的字符串连接不能解释这一点。因此,您可能会使用一个循环,getresult
中100毫秒的延迟加起来就是一个很长的等待时间。