如何解决挂起c#的任务?
在查看控制台应用程序中的一些代码时,我在如何解决挂起c#的任务?,c#,.net,task-parallel-library,C#,.net,Task Parallel Library,在查看控制台应用程序中的一些代码时,我在SecondInitialize函数中看到了嵌套的Task.whall。我决定用一个大的位置列表来测试这个函数,看看它的反应如何 我看到的是,大约有100个位置,100*100=10000Calculate调用,Start内部的t.Wait()大约需要60秒才能返回,有时甚至完全挂起。如果我尝试单击Break All,控制台应用程序甚至不会响应我的单击,visual studio就会崩溃 在SecondInitialize中使用我的“易读版本”时,返回也需
SecondInitialize
函数中看到了嵌套的Task.whall。我决定用一个大的位置列表来测试这个函数,看看它的反应如何
我看到的是,大约有100个位置,100*100=10000Calculate
调用,Start
内部的t.Wait()
大约需要60秒才能返回,有时甚至完全挂起。如果我尝试单击Break All
,控制台应用程序甚至不会响应我的单击,visual studio就会崩溃
在SecondInitialize
中使用我的“易读版本”时,返回也需要一段时间。一贯的行为
奇怪的是,每当我使用调试器,在SecondInitialize
中设置断点,然后点击continue,它将在5-7秒内完成
所以我的问题是,当我在函数内部调试时看到它更快时,为什么它正常地挂起要花很长时间?另一个问题是任务的使用是否正确
public void Start()
{
var t = CacheInitialize(locations, CancellationToken.None);
t.Wait();
}
public Task CacheInitialize(IList<Location> locations, CancellationToken token)
{
return SecondInitialize(locations, token);
}
public async Task SecondInitialize(IList<Location> locations, CancellationToken token)
{
await Task.WhenAll(locations.Select(first =>
{
return Task.WhenAll(locations.Where(second => !second.Equals(first)).Select(second =>
{
return Calculate(first, second, token);
}));
}));
//Easier to read version of ^
//var tasks = locations.SelectMany(first => locations.Where(second => !second.Equals(first)).Select(second =>
//{
// return Calculate(first, second, token);
//}));
//await Task.WhenAll(tasks);
//No Tasks.
//for (int x = 0; x < locations.Length; x++)
//{
// for (int y = 0; y < locations.Length; y++)
// {
// if (x == y)
// continue;
// await Calculate(locations[x], locations[y], token).ConfigureAwait(false);
// }
//}
}
public async Task<TripLength> Calculate(Location start, Location finish, CancellationToken token)
{
if (start == finish)
return TripLength.Zero;
var parameters = new RouteParameters
{
Coordinates = new []
{
new Coordinate(start.Latitude, start.Longitude),
new Coordinate(finish.Latitude, finish.Longitude)
}
};
var route = await RunRoute(parameters, token);
return ToTripLength(route);
}
protected Task<RouteResult> RunRoute(RouteParameters routeParams, CancellationToken token)
{
return Task.Run(async () =>
{
var routingTask = Task.Run(() =>
{
RouteResult routeResults;
var status = _routeService.Route(routeParams, out routeResults);
return routeResults;
}, token);
return await routingTask.ConfigureAwait(false);
}, token);
}
public void Start()
{
var t=CacheInitialize(位置,CancellationToken.None);
t、 等待();
}
公共任务缓存初始化(IList位置、CancellationToken令牌)
{
返回第二次初始化(位置、令牌);
}
公共异步任务SecondInitialize(IList位置、CancellationToken令牌)
{
等待任务。何时(地点)。选择(第一个=>
{
返回Task.WhenAll(locations.Where(second=>!second.Equals(first))。选择(second=>
{
返回计算(第一、第二、令牌);
}));
}));
//易于阅读的版本^
//var tasks=locations.SelectMany(第一个=>locations.Where(第二个=>!第二个.Equals(第一个)).Select(第二个=>
//{
//返回计算(第一、第二、令牌);
//}));
//等待任务。何时(任务);
//没有任务。
//对于(int x=0;x
{
var routingTask=Task.Run(()=>
{
RouterResult RouterResults;
var状态=_routeService.Route(routeParams,out routeResults);
返回路由结果;
},代币);
返回Wait routingTask.ConfigureWait(false);
},代币);
}
由于您的示例不完整且无法编译,因此很难看到您到底在做什么
但据我所知,有几个问题:
对任务调用Wait
(或Result
)。
使用ConfigureAwait(false)
将有助于避免此类问题,但不能消除所有问题。
所以,当您想要访问任务的结果时,最好总是等待任务
我看不出您试图通过在Task.WhenAll
中嵌套Task.WhenAll
来完成什么。
WhenAll
返回一个任务,您可以在没有任务的情况下等待它。WhenAll
。
您创建的每个任务都会增加一些性能开销,因此您应该尝试创建尽可能少的任务
Task.Run
等待另一个任务(由Task.Run
创建)毫无意义,因为您创建的任务超过了您的需要。
你可以只等待一个任务。运行public class Program
{
public static async Task Main( String[] args )
{
var foo = new Foo();
var sw = Stopwatch.StartNew();
await foo.Start();
sw.Stop();
Console.WriteLine($"Elapsed {sw.Elapsed} {sw.ElapsedMilliseconds}ms");
Console.ReadLine();
}
}
public class Foo
{
public async Task CacheInitialize( IList<Location> locations, CancellationToken token ) =>
await SecondInitialize( locations, token )
.ConfigureAwait( false );
public async Task<TripLength> Calculate( Location start, Location finish, CancellationToken token )
{
if ( start == finish )
return TripLength.Zero;
var parameters = new RouteParameters
{
Coordinates = new[]
{
new Coordinate( start.Latitude, start.Longitude ),
new Coordinate( finish.Latitude, finish.Longitude )
}
};
var route = await RunRoute( parameters, token );
return new TripLength();
}
public async Task SecondInitialize( IList<Location> locations, CancellationToken token )
{
var tasks = new List<Task>( locations.Count );
foreach ( var outer in locations )
foreach ( var inner in locations )
{
if ( inner.Equals( outer ) )
continue;
tasks.Add( Calculate( outer, inner, token ) );
}
await Task.WhenAll( tasks );
}
public async Task Start()
{
var locations = new List<Location>();
await CacheInitialize( locations, CancellationToken.None )
.ConfigureAwait( false );
}
protected async Task<RouteResult> RunRoute( RouteParameters routeParams, CancellationToken token )
{
return await Task
.Run( () =>
{
//RouteResult routeResults;
//var status = _routeService.Route( routeParams, out routeResults );
//return routeResults;
return new RouteResult();
},
token )
.ConfigureAwait( false );
}
}
public class Coordinate
{
public Double Latitude { get; }
public Double Longitude { get; }
public Coordinate( Double latitude, Double longitude )
{
Latitude = latitude;
Longitude = longitude;
}
}
public class RouteParameters
{
public Coordinate[] Coordinates { get; set; }
}
public class TripLength
{
public static TripLength Zero = new TripLength();
}
public class RouteResult
{
}
public class Location
{
public Double Latitude { get; }
public Double Longitude { get; }
}
公共类程序
{
公共静态异步任务主(字符串[]args)
{
var foo=new foo();
var sw=Stopwatch.StartNew();
等待foo.Start();
sw.Stop();
WriteLine($“经过的{sw.eassed}{sw.elapsedmillesons}ms”);
Console.ReadLine();
}
}
公开课Foo
{
公共异步任务缓存初始化(IList位置,CancellationToken令牌)=>
等待第二次初始化(位置、令牌)
.配置等待(错误);
公共异步任务计算(位置开始、位置完成、取消令牌)
{
如果(开始==完成)
返回三倍长度。零;
var参数=新的路由参数
{
坐标=新[]
{
新坐标(起点、纬度、起点、经度),
新坐标(终点、纬度、终点、经度)
}
};
var route=等待运行路由(参数、令牌);
返回新的三倍长度();
}
公共异步任务SecondInitialize(IList位置、CancellationToken令牌)
{
var任务=新列表(locations.Count);
foreach(外部位置的var)
foreach(位置中的内部变量)
{
if(内部等于(外部))
持续
添加(计算(外部、内部、令牌));
}
等待任务。何时(任务);
}
公共异步任务启动()
{
变量位置=新列表();
等待缓存初始化(位置,CancellationToken.None)
.配置等待(错误);
}
受保护的异步任务运行路由(RouteParameters routeParams,Ca
var combinations=( from start in locations
from finish in locations
where start!=finish
select (start,finish))
.ToArray();
RouteParameters locationsToParams((Location start,Location finish) combination)
{
return new RouteParameters {
Coordinates = new[]
{
new Coordinate( start.Latitude, start.Longitude ),
new Coordinate( finish.Latitude, finish.Longitude )
}
};
}
RouteResult callRoute(RouteParameters routeParams)
{
_routeService.Route(routeParams, out var routeResults);
return routeResults;
}
var tripLengths = from cmb in combinations.AsParallel()
let routeParams=locationsToParams(cmb)
let result=callRoute(routeParams)
select ToTripLength(result);
var finalResults = tripLengths.ToArray();
var tripLengths = from cmb in combinations.AsParallel()
.WithDegreeOfParalellism(10)
let routeParams=locationsToParams(cmb)
let result=callRoute(routeParams)
select ToTripLength(result);
var finalResults = tripLengths.ToArray();