关于等待线程结束的问题

daiwoo_wang 2018-01-03 10:19:51
写了个程序,在线程中对数据库进行操作,线程内是用WHILE(Thread.AllowRun)来循环,在主界面按EXIT按钮时,用Application.Exit()来退出,但这样会打断线程内的数据库操作,使某些表记录处于锁定状态。有什么办法在按EXIT键后,让处理数据库线程运行完,主程序才退出?
...全文
420 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
xinbada1985 2018-01-04
  • 打赏
  • 举报
回复
在WHILE里面数据库操作时做一个状态flag,分别是执行中和执行完了,点击退出时,判断一下当前是不是在执行中,如果是执行中做一个监控,看状态变成完了时,在关闭程序!如果不是执行中就直接关闭。
xuzuning 2018-01-03
  • 打赏
  • 举报
回复
不要在线程里 while。一定要有 while 的话,应放在线程外,即线程在 while 中启动 守候线程宜用异步方式实现
zmyouren1983 2018-01-03
  • 打赏
  • 举报
回复
使用BackgroundWorker,随时监控数据库处理的状态。事件未处理完程序不退出。
daiwoo_wang 2018-01-03
  • 打赏
  • 举报
回复
我还是贴下代码吧,在主进程里,有全局变量public static Boolean TProcessThreadRun = false;,目的是让子线程根据这个值来决定是否退出,而不是调用Thread.Abort() 线程的BACKGROUD属性是TRUE,然后就开始执行这个线程了,在线程里,这样工作: while (TProcessThreadRun) { //** 多线程进入,需要同步 mProcessNext.waitone(); ...互斥完成,信号恢复,mProcesNext.Set(); 然后...,包括数据库处理 Sleep(50); } 就这么简单。数据库处理包括了将某个字段置为1,处理完再将这个字段置为0,点击主窗体退出按钮, TProcessThreadRun = false;首先将线程运行标志置0,然后等待 SLEEP(1000); 再Application.Exit(); 或者用this.Close()关闭主窗体,然后无论用什么方法,都会发现数据库中某个字段为1,也就是数据库工作没有完成,因为完成了这个字段得被重新置0. 调试发现,当按退出按钮后,线程的状态编程了waitjoinsleep,也就是被阻止了。 假如不使用WHILE循环,怎么让线程持续工作?这是个守护线程。试过将BACKGROUD改为TRUE或FALSE,使用CLOSE方法,都无法让线程运行完后退出
  • 打赏
  • 举报
回复
就“等待结束”的信号机制而言,可以使用 .net 的基本的信号对象
ManualResetEvent busy;

private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
    if (busy != null)
        busy.WaitOne();
}
在你的"线程“中初始化对象
busy = new ManualResetEvent(false);
..................................
busy.Set();
不过一大堆设计凑在一起才出的这种问题,什么 Application.Exit、 While 循环、表锁定(即使在进程技术之后)、Join 之类的纠结在一堆,说明了此类 bug 总会频繁出现在这类设计之下。
  • 打赏
  • 举报
回复
重点是不应该有 while 循环设计,至于用什么退出,那是其次(按照常规做法而不要强行退出就行)。如果不改变 while 循环,那么可以说没有什么本质的改变。
daiwoo_wang 2018-01-03
  • 打赏
  • 举报
回复
大部分情况下,会在界面上放一个退出按钮,这样用户体验更好。但在编写这个事件时,会用Application.Exit()来结束这个应用。 现在的问题是,用全局布尔变量来允许线程执行,在线程里是WHILE(true)结构,当按退出按钮时,将这个线程允许运行变量置1,此时调试会发现,线程处于waitsleepjoin状态,也就是因为调用了那3个方法之一导致线线程被阻止了
  • 打赏
  • 举报
回复
异步操作数据库操作应该很短暂,例如几十毫秒、几百毫秒就结束。我猜你弄了个“死”循环,这种就是一个 bug 引出一堆 bug。你若删除 “滥用while 循环”的这种概念,你也就不会去用 Application.Exit 了,这就是问题的结症。
  • 打赏
  • 举报
回复
另外,假设你的进程强行(错误地)中断了,而你的“些表记录处于锁定状态”,这说明你使用的 DAL (数据库操作引擎)库有问题,不应该使用。如果你正常地使用 ADO.NET 或者 EF 之类的,我相信不会有这种问题。
daiwoo_wang 2018-01-03
  • 打赏
  • 举报
回复
我有一个全局变量是线程执行标志的,因为在线程中要用WHILE循环,看我的代码,使用了WHILE(标志)来执行线程,退出时将该标志置为FALSE,可能版主的意见最简单,那就是让程序‘不干净退出’,主程序退出,线程让它自然完成。当然复杂点的情况是再用一个全局变量来记录线程是否完成,完成了才让程序退出
  • 打赏
  • 举报
回复
界面上按退出按钮,关闭主窗体就行了,进程会自动安全地退出。谁让你随便写 Application.Exit 呢?
  • 打赏
  • 举报
回复
你不要把线程设置为后台线程,程序关闭时,线程不会被关闭,即所谓的不干净的退出 所以你最好在关闭事件中判断判断线程集合是否全部执行完毕,执行完毕后才执行退出
秋的红果实 2018-01-03
  • 打赏
  • 举报
回复
只能等待线程执行完,不要强行中断线程 要想在指定时间内“强行”终止线程,只好在线程自身里做文章,例如对数据库的某个操作,如果超过一定时间事务还没有完成,就回滚数据库操作 探测线程是否执行完,可以参考#1,或者使用委托实现的多线程,回调函数将汇报执行情况;用Task也可以,continuewith
秋的红果实 2018-01-03
  • 打赏
  • 举报
回复
先检测线程是否执行完,然后调用Application.Exit()
  • 打赏
  • 举报
回复
定义一个全局变量,,或者用线程池,,这样通知所有的线程要结束掉。。。释放所有的资源。。。
daiwoo_wang 2018-01-03
  • 打赏
  • 举报
回复
另外,如果线程在WHILE里启动,那么在线程外的这个WHILE里是要去轮询数据库的
daiwoo_wang 2018-01-03
  • 打赏
  • 举报
回复
这个线程也不是守护线程,就是在后台一直工作,当发现数据库有新记录时,对记录进行处理而已
daiwoo_wang 2018-01-03
  • 打赏
  • 举报
回复
有意思的是,在退出按钮中,假如不要别的代码,就留下那个ProcessThreadRun = false,那么线程可以正常完成. 按版主的意思,如果线程外去WHILE?那就是频繁的启动和结束线程了?

110,501

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧