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

发布于 2025-01-08 00:18:48 字数 2439 浏览 0 评论 0原文

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

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

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

我在 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 的完整代码。

Sorry for the lengthy post, I just want to illustrate my situation as best as possible. Read the items in bold and check the code if you want the quick gist of the issue.

I use ClickOnce to deploy a C# application, and have opted to have my application check for updates manually using the ApplicationDeployment Class rather than letting it do the update checking for me.

The program is a specialized network scanner that searches for network devices made by the company I work for. Once the main window is loaded, a prompt is displayed asking if the user would like to scan the network. If they say Yes, a scan begins which can take a minute or two to complete depending on their network settings; otherwise it just waits for the user to do some action.

One of the last things I do in Form_Load is create a new thread that checks for updates. This had all been working fine for several months through about 12 releases and has suddenly stopped working. I didn't change the update code at all, nor change the sequence of what happens when the app starts.

In staring at the code, I think I see why it is not working correctly and wanted to confirm if what I think is correct. If it is, it begs the question as to why it DID work before - but I'm not too concerned with that either.

Consider the following code:

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???
    }
}

When the CheckForUpdateAsync() callback completes, if no update is available the method call simply returns; if an update IS available, I use a loop to block until 2 things occur: The user has dismissed the "Would you like to scan prompt" AND no scan is currently running.

The loop looks like this, which takes place in ad_CheckForUpdateCompleted:

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

I sleep for 5 seconds because I figured this was happening in a separate thread and it has seemed to work well for a while.

My main question about the above code is:
When ad.CheckForUpdateAsync(); is called from CheckForUpdate does the thread I created in Form1_Load terminate (or might it terminate)? I suspect it may because the subsequent Async call causes the method to return, and then start another thread?

The only reason I am confused is because this method WAS working for so long without hanging the application and now all of the sudden it hangs and my best effort at debugging revealed that it was that Sleep call blocking the app.

I'd be happy to post the full code for frmAppUpdater.cs if it would be helpful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

温柔戏命师 2025-01-15 00:18:48

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

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

如果您怀疑 Sleep 导致应用程序挂起,那么这两个变量 AppGlobals.ScanInProgressAppGlobals.ScanPromptVisible 可能始终设置为 >正确!您应该开始查看将它们设置为 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 提供了一系列非常适合线程同步的,< code>WaitHandle 就是其中之一。

When ad.CheckForUpdateAsync(); is called from CheckForUpdate does
the thread I created in Form1_Load terminate (or might it terminate)?

If the CheckForUpdateAsync() call is asynchronous then yes, the thread will terminate, no it won't otherwise.

If you suspect the Sleep to have caused the application hang then these two variables AppGlobals.ScanInProgress and AppGlobals.ScanPromptVisible are probably always set to true! You should start looking at the code that is setting them to true and see what is going on there.

In order to avoid an application hang, you could introduce a variable to avoid sleeping indefinitely:

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

I personally do not like using Sleep for thread synchronization. .NET offers a bunch of classes that are perfect for thread synchronization, WaitHandle being one of them.

岁月蹉跎了容颜 2025-01-15 00:18:48

请参阅这篇文章异步委托与线程/线程池?

您的表单加载方法似乎是做同步工作。您提到您正在使用 clickonce 部署。上一版本后二进制位置是否发生更改,或者对此资源的权限是否发生更改。看起来线程中的工作(检查更新)永远不会完成,也永远不会交回表单。

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

下一步,我将浏览 http://msdn.microsoft.com /en-us/library/ms229001.aspx 并进行故障排除

See this post at Asynchronous Delegates Vs Thread/ThreadPool?

your form load method seems to be doing synchronous work. you mention that you are using clickonce deployment. Has the binary location changed after the previous release or has permissions on this resource changed. Looks like the work (checkupdates) in the Thread is never finishing and is never handed back to the form.

as an immediate fix, I would change the Thread approach to Delegate - if you use delegate, then this becomes less of a customer issue (the form will respond to end user) but the underlying problem remains.

as the next step, i would go through http://msdn.microsoft.com/en-us/library/ms229001.aspx and do the troubleshoot

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文