Form_Load中的线程-应用程序现在突然挂起

本文关键字:应用程序 突然 挂起 线程 Load Form | 更新日期: 2023-09-27 18:25:24

很抱歉发了这么长的帖子,我只是想尽可能地说明我的情况如果你想快速了解问题的要点,请阅读粗体项目并检查代码

我使用ClickOnce来部署C#应用程序,并选择让我的应用程序使用ApplicationDeployment类手动检查更新,而不是让它为我做更新检查。

该程序是一个专门的网络扫描仪,用于搜索我工作的公司制造的网络设备。一旦加载了主窗口,就会显示一个提示,询问用户是否愿意扫描网络。如果他们说是,扫描就会开始,根据他们的网络设置,扫描可能需要一两分钟才能完成;否则,它只是等待用户执行一些操作。

我在Form_Load中做的最后一件事是创建一个新线程来检查更新。几个月来,通过大约12次发布,这一切都很顺利,现在突然停止了工作。我根本没有更改更新代码,也没有更改应用程序启动时的顺序。

在盯着代码看的时候,我想我明白了为什么它不能正确工作,并想确认我认为的是否正确。如果是的话,这就引出了为什么它以前确实有效的问题——但我也不太担心

考虑以下代码:

frmMain.cs

private void Form1_Load(object sender, EventArgs e)
{
    // set up ui, load settings etc
    Thread t = new Thread(new ParameterizedThreadStart(StartUpdateThread));
    t.Start(this);
}
private void StartUpdateThread(object param)
{
    IWin32Window owner = param as IWin32Window;
    frmAppUpdater.CheckForUpdate(owner);
}

frmAppUpdater.cs

public static void CheckForUpdate(IWin32Window owner)
{
    if (ApplicationDeployment.IsNetworkDeployed) {
        Console.WriteLine("Going to check for application updates.");
        parentWindow = owner;
        ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
        ad.CheckForUpdateCompleted += new CheckForUpdateCompletedEventHandler(ad_CheckForUpdateCompleted);
        ad.CheckForUpdateProgressChanged += new DeploymentProgressChangedEventHandler(ad_CheckForUpdateProgressChanged);
        ad.CheckForUpdateAsync();
        // CAN/WILL THE THREAD CREATED IN FORM1_LOAD BE TERMINATED HERE???
    }
}

CheckForUpdateAsync()回调完成时,如果没有可用的更新,则方法调用简单地返回;如果有可用的更新,我会使用一个循环来阻止,直到出现两件事:用户已经取消了"你想扫描提示吗",并且当前没有扫描正在运行。

循环如下所示,发生在ad_CheckForUpdateCompleted:中

while (AppGlobals.ScanInProgress || AppGlobals.ScanPromptVisible) {
    System.Threading.Thread.Sleep(5000);
}

我睡了5秒钟,因为我认为这是在一个单独的线程中发生的,而且它似乎已经运行了一段时间。

我对上述代码的主要问题是:
当从CheckForUpdate调用ad.CheckForUpdateAsync();时,我在Form1_Load中创建的线程是否终止(或者可能终止)?我怀疑这可能是因为后续的Async调用导致方法返回,然后启动另一个线程?

我感到困惑的唯一原因是,这个方法在没有挂起应用程序的情况下工作了很长时间,现在突然挂起了,我在调试时尽了最大努力,结果发现是睡眠调用阻塞了应用程序。

如果有帮助的话,我很乐意发布frmAppUpdater.cs的完整代码。

Form_Load中的线程-应用程序现在突然挂起

当从CheckForUpdate调用ad.CheckForUpdateAsync();时我在Form1_Load中创建的线程终止(或者可能终止)?

如果CheckForUpdateAsync()调用是异步的,那么是的,线程将终止,否则不会终止。

如果您怀疑Sleep导致应用程序挂起,那么这两个变量AppGlobals.ScanInProgressAppGlobals.ScanPromptVisible可能总是设置为true!您应该开始查看将它们设置为true的代码,看看那里发生了什么。

为了避免应用程序挂起,可以引入一个变量来避免无限期睡眠:

int nTrials = 0;
while ((AppGlobals.ScanInProgress || AppGlobals.ScanPromptVisible) && (nTrials < 5)) {
    System.Threading.Thread.Sleep(5000);
    nTrials++;
}
// Check the results and act accordingly

我个人不喜欢使用Sleep进行线程同步。NET提供了一系列非常适合线程同步的类,WaitHandle就是其中之一。

请参阅异步委托与线程/线程池?

您的表单加载方法似乎正在执行同步工作。您提到您正在使用clickonce部署。在上一版本之后二进制位置是否已更改,或者对此资源的权限是否已更改。看起来线程中的工作(checkupdates)从未完成,也从未返回到表单。

作为一个即时的解决方案,我会将Thread方法更改为Delegate——如果您使用Delegate,那么这就不再是客户问题(表单将响应最终用户),但潜在的问题仍然存在。

作为下一步,我会http://msdn.microsoft.com/en-us/library/ms229001.aspx并对进行故障排除