加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 关闭WinForm应用程序时的一次性对象生命周期

发布时间:2020-12-15 22:04:42 所属栏目:百科 来源:网络整理
导读:我有一个连接到数据库的 Windows窗体应用程序.所有重型SQL查询都在后台线程中实现,因此它们不会阻塞主线程.其中一些查询需要数据库事务.使用关键字初始化所有Db对象以确保正确处理: using (conn = OpenConnection()){ using (tran = conn.BeginTransaction(
我有一个连接到数据库的 Windows窗体应用程序.所有重型SQL查询都在后台线程中实现,因此它们不会阻塞主线程.其中一些查询需要数据库事务.使用关键字初始化所有Db对象以确保正确处理:

using (conn = OpenConnection())
{
    using (tran = conn.BeginTransaction())
    {
        // Do stuff
    }
}

现在,一些用户是住院病人,他们只是在应用程序在后台线程中有活动事务时关闭应用程序.我们的数据库管理员发现这些事务在数据库上仍然活动了几分钟甚至更长时间,这是一个问题,因为打开事务会锁定数据.

那么,当用户决定关闭应用程序时,这些线程中的线程和一次性对象会发生什么?线程是使用Task.StartNew()方法创建的.

解决方法

任务

Foreground and Background Threads:

a background thread does not keep the managed execution environment running. Once all foreground threads have been stopped in a managed process (where the .exe file is a managed assembly),the system stops all background threads and shuts down.

这也适用于线程池中的线程,这些线程在启动新任务时默认使用,而不指定其他选项:

Task Schedulers

The default task scheduler is based on the .NET Framework 4 ThreadPool

Foreground and Background Threads:

Threads that belong to the managed thread pool (that is,threads whose IsThreadPoolThread property is true) are background threads.

关于申请终止的事实

在那之后,我还没有找到任何进一步的信息,在线程终止后发生了什么.我所做的,是简单的测试:

static void Main(string[] args)
{
    Task.Factory.StartNew(Method);
    Task.Delay(1000);
}

static void Method()
{
    try
    {
        while (true) { }
    }
    finally
    {
        File.WriteAllText(@"C:PolygonTest.txt","test");
    }
}

答案是,最终块没有被执行.

解决方案

ThreadAbortException – 不在这里

像ThreadAbortException这样的.NET中有一些功能称为线程终止的答案,但是:

When the common language runtime (CLR) stops background threads after all foreground threads in a managed executable have ended,it does not use Thread.Abort.

Process.Exited事件 – 不在这里

如果您运行其他进程,可以使用以下代码:

var myProcess = new Process();
myProcess.EnableRaisingEvents = true;
myProcess.Exited += new EventHandler(CleanUp);

但是,对于当前流程,这也不起作用.

AppDomain.CurrentDomain.ProcessExit – 有效

但是,Avneesh建议的解决方案适用于当前流程:

static void Main(string[] args)
{
    AppDomain.CurrentDomain.ProcessExit += CleanUp;

    Task.Factory.StartNew(Method);
    Task.Delay(1000);
}

static void Method()
{
    try
    {
        while (true) { }
    }
    finally
    {
        CleanUp(null,EventArgs.Empty);
    }
}

static void CleanUp(object sender,EventArgs args)
{
    File.WriteAllText(@"C:PolygonTest.txt","test");
}

流程终止

有关rosources的问题的答案可以在Terminating a Process文章中找到:

  • Any remaining threads in the process are marked for termination.
  • Any resources allocated by the process are freed.
  • All kernel objects are closed.
  • The process code is removed from memory.
  • The process exit code is set.
  • The process object is signaled.

以及如何终止进程:

  • Any thread of the process calls the ExitProcess function. Note that some implementation of the C run-time library (CRT) call ExitProcess if the primary thread of the process returns.
  • The last thread of the process terminates.
  • Any thread calls the TerminateProcess function with a handle to the process.
  • For console processes,the default console control handler calls ExitProcess when the console receives a CTRL+C or CTRL+BREAK signal.
  • The user shuts down the system or logs off.

数据库连接

连接是一种资源,因此如果处理终止,则释放其所有资源.我检查了它在实践中的样子.

C#代码:

SqlConnection connection = new SqlConnection("Data Source=.;Initial Catalog=[database_name];Integrated Security=True");
connection.Open();
Debugger.Launch();
connection.Close();
connection.Dispose();

会话查找的T-SQL查询:

SELECT COUNT(*) FROM sys.dm_exec_sessions
WHERE nt_user_name = '[user_name]' AND program_name = '.Net SqlClient Data Provider'

我注意到,对于每个新连接,都创建了新会话.最有趣的是,在明确关闭或处理连接后,该会话未被释放.但是 – 目前我们感兴趣的领域 – 会话在申请流程终止时被释放.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读