Merge pull request #8 from dotnet-campus/t/lindexi/App

修复某个启动项抛出异常后续的启动项不会执行
This commit is contained in:
Shaojun Li
2022-06-15 09:00:10 +08:00
committed by GitHub
3 changed files with 39 additions and 9 deletions

View File

@@ -76,13 +76,11 @@ namespace dotnetCampus.ApplicationStartupManager
//}
_dispatcher = dispatcher;
_shouldSetThreadPool = shouldSetThreadPool;
if (shouldSetThreadPool)
{
ThreadPool.GetMinThreads(out _workerThreads, out _completionPortThreads);
//启动期间存在大量的线程池调用包含IO操作而创建的多数线程在等待 IO 时都是不会被调度的
//设置更多的初始化线程数可以减少启动期间的线程调度等待
ThreadPool.SetMinThreads(Math.Max(_workerThreads, 16), Math.Max(_completionPortThreads, 16));
}
Context = new StartupContext(logger, /*configurationRepo,*/
@@ -90,6 +88,8 @@ namespace dotnetCampus.ApplicationStartupManager
Logger.RecordTime("ManagerInitialized");
}
private readonly bool _shouldSetThreadPool;
///// <summary>
///// 配置被 <see cref="StartupManager"/> 管理的程序集。
///// 只有被管理的程序集中的启动信息、依赖注入信息才会被执行。
@@ -251,6 +251,13 @@ namespace dotnetCampus.ApplicationStartupManager
Logger.RecordTime("GraphBuilded");
}
if(_shouldSetThreadPool)
{
//启动期间存在大量的线程池调用包含IO操作而创建的多数线程在等待 IO 时都是不会被调度的
//设置更多的初始化线程数可以减少启动期间的线程调度等待
ThreadPool.SetMinThreads(Math.Max(_workerThreads, 16), Math.Max(_completionPortThreads, 16));
}
var dispatcher = _dispatcher;
foreach (var wrapper in Graph)
{
@@ -269,13 +276,15 @@ namespace dotnetCampus.ApplicationStartupManager
Logger.RecordTime("AllStartupTasksCompleted");
Debug.WriteLine(Logger);
#pragma warning disable CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法
dispatcher.InvokeAsync(() =>
Logger.ReportResult(Graph.OfType<IStartupTaskWrapper>().ToList()));
#pragma warning restore CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法
ThreadPool.SetMinThreads(Math.Max(_workerThreads, 8), Math.Max(_completionPortThreads, 8));
if(_shouldSetThreadPool)
{
ThreadPool.SetMinThreads(Math.Max(_workerThreads, 8), Math.Max(_completionPortThreads, 8));
}
}
private List<StartupTaskWrapper> BuildStartupGraph()

View File

@@ -28,15 +28,29 @@ namespace dotnetCampus.ApplicationStartupManager
{
return await Task.Run(async () =>
{
await RunAsync(context);
CompletedSource.SetResult(null);
try
{
await RunAsync(context);
}
finally
{
// 即使有异常,也是使用 SetResult 方法,因为启动项不会因为所依赖的启动项抛出异常而不执行
CompletedSource.SetResult(null);
}
return Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture);
});
}
else
{
await RunAsync(context);
CompletedSource.SetResult(null);
try
{
await RunAsync(context);
}
finally
{
// 即使有异常,也是使用 SetResult 方法,因为启动项不会因为所依赖的启动项抛出异常而不执行
CompletedSource.SetResult(null);
}
return Thread.CurrentThread.Name ??
Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture);
}

View File

@@ -27,6 +27,13 @@ namespace dotnetCampus.ApplicationStartupManager
public bool UIOnly { get; internal set; }
public StartupCriticalLevel CriticalLevel { get; set; }
#if DEBUG
/// <summary>
/// 启动项是否执行完成,这是一个调试属性
/// </summary>
public Task StartupTaskResult => TaskBase.TaskResult;
#endif
public StartupTaskWrapper(string startupTaskKey, StartupManagerBase manager)
{
_manager = manager;