从网络驱动器启动的c#.net4应用程序需要很长时间才能加载

时间:2011-03-04 01:39:37

标签: c# .net networking splash-screen drive

让我更好地解释一下我的情景。我想从网络驱动器启动.exe。我注意到,如果您检入Win XP任务管理器,带有1个组件(进度条)的小型.net 4表单大约需要20mb的内存。因此,一旦加载了splash表单,任务栏中就会占用大约20mb的内存。

因此,如果从网络驱动器启动.exe,则客户端计算机必须等到它将整个表单加载到内存中然后显示出来。这需要大约2-3分钟。所以它必须等待20mb加载。从网络驱动器启动.exe时,立即显示启动画面的最佳方法是什么?说而不是等待20MB完全下载,是否可以在仅少于1mb下载到客户端内存时显示启动画面?你能提供一些关于如何做到这一点的建议吗?

我通过查看客户端计算机上的任务管理器检查了这一点,直到.exe达到大约20 MB,然后显示启动表单。然后等待直到.exe达到大约40MB才能显示主窗体。我希望在从网络驱动器启动exe后不到两秒钟内显示启动画面,这样用户就知道exe将在大约2-3分钟内完成加载。那么如何实现呢?

顺便说一下,加载需要很长时间,因为客户端计算机位于站点外,并且有一个VPN将计算机连接到中央文件服务器。这就是为什么加载需要一段时间,因为上传链接最多1Mb。但是一旦.exe完成加载就没有缓慢。最好的方法是拥有终端服务或Citrix。但这不是现在的选择。或者在客户端计算机上安装每个.exe,但我不想走这条路。

5 个答案:

答案 0 :(得分:1)

查看ClickOnce部署。潜在地,它将允许您保留单个网络副本以便于部署,但除非已更新,否则将使客户端无需下载应用程序。

http://msdn.microsoft.com/en-us/library/t71a733d

答案 1 :(得分:0)

您可以考虑构建第二个只执行以下操作的应用程序:

  1. 显示启动画面

  2. 启动指向远程exe的新Windows进程。

  3. -

    我认为这个问题包含了您需要的代码的近似值:

    How know when a winform is loaded by Process.Start?

答案 2 :(得分:0)

任务管理器进程选项卡中的内存使用仅限本地,不会从联网计算机下载!从网络驱动器加载应用程序时,它仅下载可执行文件并在本地执行;这就是每个操作系统总是这样做的,它不是在服务器上执行的,而是流式传输的。

我有一个简报在这里发送应用程序,例如15kb exe,加载时RAM使用4.3mb(大量数据列表,这是预期的)

从美国的服务器通过VPN加载到我的本地机器(我在澳大利亚的ADSL 1,512链接......所以ULTRA很慢!)它在〜1-2秒内加载应用程序并在那里我无法在1秒钟内下载4.3mb ...我希望:)

那么你能对你的问题做些什么呢?

如果可执行文件很大并且包含嵌入式资源(图像,视频,列表,XML等)......你可以改为使用外部文件并为用户显示加载窗口,也许本地缓存文件也是如此需要完成一次,然后快速启动应用程序。可以通过应用程序检查并重新下载对资源的更改

如果应用程序可执行文件很小并且没有访问外部文件/资源​​(在联网文件夹中或在线),那么您只需管理一些网络问题:)

答案 3 :(得分:0)

.Net运行时只在需要时加载程序集 - 如果你保持可执行程序尽可能小(只显示启动屏幕所需的最小值)并将其余代码放入更大的组件中然后理论上在需要加载较大的装配之前,可以非常快速地显示启动画面。

实现这一目标的关键是了解.Net框架何时尝试加载程序集 - 更确切地说,它将在开始执行引用该程序集中包含的类型的任何方法之前加载程序集。尝试使用以下程序来更好地理解这一点:

// Contained in FirstAssembly.exe
class Program
{
    static void Main()
    {
        PrintLoadedAssemblies("start of Main");
        innerMain();
    }

    static void innerMain()
    {
        PrintLoadedAssemblies("start of innerMain");
        OtherClass obj;
    }

    static void PrintLoadedAssemblies(string point)
    {
        Console.WriteLine("Loaded assemblies at {0}", point);
        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            Console.WriteLine(assembly.FullName);
        }
    }
}

// Contained in OtherAssembly.dll
class OtherClass
{

}

有了这些知识,我们现在知道为了在加载第二个更大的组件之前显示我们的启动画面,我们需要确保在执行任何引用我们较大组件中的任何类型的方法之前显示我们的启动画面 - 我很难对此进行测试,但如果我们有一个相当标准的闪屏:

static void Main()
{
    Application.Run(new SplashScreen());
}

然后我们应该引用较大程序集中的任何类型的第一点应该是SplashScreen_Shown事件,例如:

void SplashScreen_Shown(object sender, EventArgs e)
{
    (new MainForm()).Show();
    this.Hide();
}

另请注意,这将发生在主/ UI线程上,因此在加载较大的程序集时,启动画面没有响应 - 如果这是不可接受的,那么您需要重构上面的内容,以便包含{{1引用是在异步线程中。

答案 4 :(得分:-1)

嘿,谢谢你的回答。在你的建议之后我想到了以下解决方案。 A已经构建了一个控制台应用程序,当您从网络驱动器启动它时,它会非常快速地启动。在两秒钟内。这个控制台应用程序将是我的启动画面,不是很漂亮,但至少用户会知道发生了什么。控制台exe将启动.exe我想真正加载,至少用户将知道它的加载,并将需要几分钟加载。如果可能,控制台应用程序将显示剩余时间。我现在必须弄清楚如何使用控制台应用程序执行此操作。一旦主.exe加载我然后必须关闭控制台应用程序。

任何人都知道如何从控制台应用程序执行此操作吗?