在Form_Load中进行线程处理 - 应用程序现在突然挂起

时间:2012-02-22 21:52:13

标签: c# winforms multithreading clickonce

对于冗长的帖子感到抱歉,我只是想尽可能地说明我的情况。 以粗体显示项目,如果您想快速解决问题,请查看代码。

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

该程序是一个专门的网络扫描程序,用于搜索我工作的公司制作的网络设备。加载主窗口后,将显示一个提示,询问用户是否要扫描网络。如果他们说是,则开始扫描,这可能需要一两分钟才能完成,具体取决于他们的网络设置;否则它只是等待用户做一些动作。

我在Form_Load中做的最后一件事是创建一个检查更新的新线程。通过大约12个版本,这几个月都运行良好,突然停止工作。我根本没有更改更新代码,也没有更改应用程序启动时发生的顺序。

在盯着代码时,我想我明白为什么它不能正常工作并想确认我认为是否正确。如果是的话,它就会问到为什么它之前的DID工作 - 但我也不太关心它。

请考虑以下代码:

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秒钟,因为我认为这是在一个单独的线程中发生的,它似乎在一段时间内运作良好。

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

我感到困惑的唯一原因是因为这种方法可以工作很长时间而不会挂起应用程序,现在突然间它会挂起并且我在调试时的最大努力表明睡眠调用阻止了应用程序。

如果它有用,我很乐意发布frmAppUpdater.cs的完整代码。

2 个答案:

答案 0 :(得分:1)

  

从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提供了一堆classes,非常适合线程同步,WaitHandle就是其中之一。

答案 1 :(得分:1)

请参阅Asynchronous Delegates Vs Thread/ThreadPool?

上的这篇文章

你的表单加载方法似乎正在做同步工作。你提到你正在使用clickonce部署。在先前版本之后二进制位置是否已更改,或者是否已更改此资源的权限。看起来Thread中的工作(checkupdates)永远不会完成,并且永远不会返回到表单。

作为一个立即修复,我会将Thread方法更改为Delegate - 如果您使用委托,那么这将变成一个客户问题(表单将响应最终用户),但潜在的问题仍然存在。

作为下一步,我将通过http://msdn.microsoft.com/en-us/library/ms229001.aspx并进行问题排查