C# 应用程序无法关闭。

3
我在使用基于多种表单和线程的应用程序时遇到了麻烦。线程在应用程序结束之前关闭,但即使如此,我也无法以100%的准确性终止我的应用程序。
有时进程仍然继续工作,但没有任何显示(包括表单或线程)。我认为问题出在program.cs上,几乎确定是这样,所以我将在这里粘贴代码。
 private static Process old;
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        XmlConfigurator.Configure();
        if (PriorProcess() != null)
        {
            try
            {
                old.Kill();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Ja existe uma instancia do SpotLight em execucao.", "Aviso");
                return;
            }                
        }

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Support());

    }



    public static Process PriorProcess()
    {
        Process curr = Process.GetCurrentProcess();
        Process[] procs = Process.GetProcessesByName(curr.ProcessName);
        foreach (Process p in procs)
        {
            if ((p.Id != curr.Id) && (p.MainModule.FileName == curr.MainModule.FileName))
            {
                old = p;
                return p;
            }
        }
        return null;
    }

New Support() 是应用程序中显示的第一个表单。

这是线程的代码:

private void check_calls()
{
        while (stop==false)
    {
        string actualTime = DateTime.Now.ToString("T");
        connection = new MySqlConnection(ConnectionString);
        MySql.Data.MySqlClient.MySqlCommand msqlCommand = new MySql.Data.MySqlClient.MySqlCommand();
        msqlCommand.Connection = connection;
        msqlCommand.CommandText = "Select cd.uniqueid,sup.timespan from contactCenterDevel.cc_cdr_support_pending sup, vboxZon.cdr cd WHERE sup.phone=cd.src AND cd.finish=0 AND cd.accountcode='serviin' AND cd.duration >0 AND cd.lastapp='Vxml' ORDER BY cd.calldate DESC LIMIT 1";

        try
        {
            connection.Open();
            MySql.Data.MySqlClient.MySqlDataReader msqlReader = msqlCommand.ExecuteReader();
            while (msqlReader.Read())
            {
                int timespanCompare = convertTimetoSecs(msqlReader.GetString(1));
                int actualtimeCompare = convertTimetoSecs(actualTime);

                if (timespanCompare < actualtimeCompare)
                {
                    updateFlagCDR(msqlReader.GetString(0));
                }
            }
        }
        catch (Exception er)
        { MessageBox.Show("Mysql actions error: " + er); }
        finally
        { connection.Close(); }

       Thread.Sleep(10000);
    }   
}

当我的注销函数中的标志“stop”更改为true时,此线程停止。我已经尝试过注释掉“thread.sleep”,但问题仍然出现。


请问您能否发布主应用程序线程结束的代码? - GregRos
你可以这样做:当你的应用程序处于幽灵模式时,运行VS并将其附加到你的进程上。然后,暂停执行并显示线程(调试菜单=>窗口=>线程)。是否有你启动的任何线程(直接或间接)? - Kek
数据库连接线程的代码已插入。 - AndreLucas13
@Kek 我按照你说的做了,但是没有线程仍在运行。 - AndreLucas13
我解决了这个问题。我的应用程序连接到Asterisk服务器,并将其用作集成来应用VOIP。Asterisk运行一个线程,允许您“登录和注销”服务器,并且该线程始终在等待用户代码部分的最终响应。在检查Asterisk源代码时,我注意到该线程不是IsBackground,而是使用Sleep等待注销函数。这就是为什么大多数情况下应用程序无法关闭的原因,感谢大家的支持。 - AndreLucas13
3个回答

5
通常情况下,这是因为您有一些从未终止的线程。为了避免这种情况,如果您希望您的应用程序无论非 UI 线程的状态如何都能结束,您应该将它们创建时的 IsBackground 标志设置为 true。

是的,我已经在每个线程上都有了那个。我只有一个使用while运行的线程,但在我的应用程序“注销”之前,我会用一个标志来结束它。更让我感到好奇的是,有时应用程序会正常结束,但大多数情况下不会,因此考虑到这一事实,我也认为这是一个线程问题,尽管它们在应用程序结束之前被关闭。 - AndreLucas13
如果可能的话,请不要关闭、终止、加入(join)、设置标志(flag)、轮询任何标志或等待任何事件。只需退出应用程序即可。操作系统将会清除所有线程,无论它们处于什么状态或在哪个核心上运行,都不会有问题。 - Martin James
@Martin James 我已经尝试过了,看起来问题不在于创建、使用或关闭线程,但我仍然找不到解决方案。 - AndreLucas13

1
我解决了这个问题。我的应用程序连接到一个Asterisk服务器,并将其用作VOIP的集成应用。Asterisk运行一个线程,允许您“登录和注销”服务器,并且该线程始终在等待用户代码部分的最终响应。检查Asterisk源代码时,我注意到该线程不是IsBackground,而是使用Sleep等待注销函数。这就是为什么大多数情况下应用程序无法关闭的原因,感谢你们的支持。

和 Skype 一样。 - Sam

0

除非有绝对必要明确终止线程(例如规范要求在退出时关闭所有数据库连接,而您有这样的连接绑定到创建它们的线程/线程),否则不要明确终止线程!

如果可以,请让操作系统来做。它比由您或我编写的用户代码更擅长此项工作。


那么问题是线程终止得太早了吗?应用程序终止之前需要终止其中一个线程,因为它有数据库连接,但这是唯一一个具有数据库连接的线程。难道没有一种方法可以在用户代码的某个点上“不关心”地终止所有进程、线程和窗体吗? - AndreLucas13
请纠正我,如果您的线程处于睡眠或等待AutoResetEvent状态,而您没有显式地将该线程设置为IsBackground,则应用程序不会退出,直到该线程被显式终止,是吗?(至少这是我遇到的问题,我通过设置IsBackground解决了它) - Kek
是的,具有睡眠功能的线程已将isBackground设置为true。我目前正在测试问题是否是一个表单,即使用户界面关闭它,它仍在内存中运行。 - AndreLucas13

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接