C# 如何在启动屏幕上报告将程序集加载到.Net中当前AppDomain的进度?

C# 如何在启动屏幕上报告将程序集加载到.Net中当前AppDomain的进度?,c#,wpf,assemblies,progress,C#,Wpf,Assemblies,Progress,我在显示加载到AppDomain.CurrentDomain的程序集的进度时遇到了一些困难 我想做的是显示一个有进度条的启动屏幕,我想在每个程序集加载到AppDomain的内存中时更新这个进度条。这样,用户就可以看到应用程序启动的进度 我不在乎在渲染初始屏幕之前加载程序集,初始屏幕实际上只是一个带有进度条的标准WPF窗口。一旦启动屏幕加载,我想在加载程序集时报告它们。我没有手动加载这些程序集 到目前为止,我已经用以下标记处理了App.xaml中的启动事件: Startup="Applicatio

我在显示加载到AppDomain.CurrentDomain的程序集的进度时遇到了一些困难

我想做的是显示一个有进度条的启动屏幕,我想在每个程序集加载到AppDomain的内存中时更新这个进度条。这样,用户就可以看到应用程序启动的进度

我不在乎在渲染初始屏幕之前加载程序集,初始屏幕实际上只是一个带有进度条的标准WPF窗口。一旦启动屏幕加载,我想在加载程序集时报告它们。我没有手动加载这些程序集

到目前为止,我已经用以下标记处理了App.xaml中的启动事件:

Startup="Application_Startup"
相应的启动代码如下所示:

private void Application_Startup(object sender, StartupEventArgs e)
{
SplashScreen.Show<SplashScreen>();
AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad;
}

void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
    SplashScreen.CallSplashScreenMethod<SplashScreen>(x => x.Text(args.LoadedAssembly.GetName().Name));
}
或者通过实现

我无法通过简单的“Directory.GetFiles().Length”来获取要加载的程序集总数。原因是CLR没有以任何特定顺序加载程序集。它似乎从应用程序根目录加载一些程序集,然后从GAC加载一些程序集,然后从应用程序根目录加载更多程序集


我想知道的是,是否有办法获得要加载的剩余程序集的列表。

正如其他人所说,您不能假设10个加载的程序集中有9个意味着90%。然而,你可以使这些假设更加现实

扫描将要加载的所有程序集的文件信息,以便获得每个程序集的文件大小。现在为“平均值”集合创建一个加权值

var totalSize =  assemblies.Select(x=> x.FileSize).Sum();
var averageSize = totalSize / assemblies.Count();

var averageChange = averageSize / totalSize;
假设进度条的比例为0到1,则每次加载另一个程序集时,只需添加
averageChange

或者您可以实际计算加载的字节数与进度条的总大小。我个人会使用我的平均方法来防止单个程序集的进度条从[--]变为[--]。用户不习惯于非线性变化,也不容易信任非线性变化。给他们一个线性增加的进度条,几乎完全在加载完成时结束,这给了人们正确的感觉,事情正在工作,很快就会完成。进度条中不稳定的跳跃会让用户感觉系统不稳定且不可信


有一件事我不能低估,那就是用进度条激怒用户是多么容易。没有什么比一个进度条更让用户恼火的了,它可以快速填充99%的点击率并停止。这让他们觉得节目冻结了。他们还需要视觉指示,在任何米之间东西没有冻结。他们也不想长时间坐在那里(请注意,这是几秒钟)看到进度条填满,然后又返回到零。

这将假定您确切知道需要多长时间。你当然不知道。您最多可以对程序集进行计数,但这不太可能具有代表性,因为加载程序集是盲目快速的。程序集中的JITT和运行代码需要时间。保留您所拥有的。您能数一数调用
CurrentDomain_AssemblyLoad
的次数并根据该次数更新进度条吗?@Trispid当我向项目中添加其他功能时,程序集的数量很可能会发生变化。谢谢你和Hans到目前为止的评论。那么每次程序集的数量都会改变吗?另外,在你的评论开头加上@Trispid,这样我会得到一个提醒。@HansPassant谢谢你的评论。如果执行被调用代码的JIT过程花费的时间最长,我将如何表示这一点?我想有什么方法可以根据初始化或加载的类型事件报告进度?同样,我不介意基于某种计数来做这件事,我不是在寻找毫秒精度。我喜欢这个答案,我对它投了更高的票,因为这是一个好主意,并强调了一个关于加载条的相当好的观点。谢谢你花时间为我写这篇文章!但这不完全是我想要的。问题是我无法扫描GAC(全局程序集缓存)中包含的程序集的文件信息。我需要知道如何获得需要加载的所有程序集的计数,这些文件不一定都在同一个目录中,这意味着我不能只做一个简单的“获取目录'x'中的文件信息”。程序集似乎也没有按任何特定顺序加载。
文件不一定都在同一目录中
您应该有足够的信息来探测所有位置。我不会与GAC为伍,只会对平均变化值进行缩放,这一切都很好。你不可能做到完美,你只需要付出最大的努力。
var totalSize =  assemblies.Select(x=> x.FileSize).Sum();
var averageSize = totalSize / assemblies.Count();

var averageChange = averageSize / totalSize;