如何判断某个线程"包括他下面的所有子线程"都已全部结束

橘子皮... 2018-11-04 08:33:09

Imports System.Threading
Imports System.Threading.Tasks

Public Class Form1
Dim bStop1 As Boolean = False
Dim bStop2 As Boolean = False
Dim bStop3 As Boolean = False
Dim bStop4 As Boolean = False

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim tt As New List(Of Task)

bStop1 = False : bStop2 = False : bStop3 = False : bStop4 = False

For i = 0 To 1
Dim ta = Task.Factory.StartNew(Sub()
Do
Task.Factory.StartNew(Sub()
Do
Task.Factory.StartNew(Sub()
Do
Task.Factory.StartNew(Sub()
Do
Me.Invoke(Sub() Me.Label5.Text = "4|" & Now.Millisecond)
Thread.Sleep(100)
Loop Until bStop4
End Sub, TaskCreationOptions.AttachedToParent)

Me.Invoke(Sub() Me.Label4.Text = "3|" & Now.Millisecond)
Thread.Sleep(100)
Loop Until bStop3
End Sub, TaskCreationOptions.AttachedToParent)

Me.Invoke(Sub() Me.Label3.Text = "2|" & Now.Millisecond)
Thread.Sleep(100)
Loop Until bStop2
End Sub, TaskCreationOptions.AttachedToParent)

Me.Invoke(Sub() Me.Label2.Text = "1|" & Now.Millisecond)
Thread.Sleep(100)
Loop Until bStop1
End Sub)
tt.Add(ta)
Next

Task.Factory.StartNew(Sub() Task.WaitAll(tt.ToArray)).ContinueWith(Sub() MsgBox("OK"))
End Sub


Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
bStop1 = True
End Sub

Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
bStop2 = True
End Sub

Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
bStop3 = True
End Sub

Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
bStop4 = True
End Sub
End Class


问题: 如何判断tt(每个线程下包含几层子线程)所有线程全部已结束??比如在所有子线程下都设置 TaskCreationOptions.AttachedToParent这样才行?是的话有无简单点的写法?
...全文
110 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
例如父线程 x,它调用了子线程(也就是异步地)执行了任务 a、b、c,那么x 可能立刻就结束了!x 并不需要阻塞。 然后过一段时间,a 任务(在它所在的线程)回调了一个委托,b任务直接结束了,这都是可能的。在异步编程中,设计流程的节点在于”回调“委托。而 Task 的 await 也就是回调委托(await 左边以及后边的代码都是回调任务中的内容)。 所以一旦看到什么”下面的子线程、包含子线程“这类话,不但是你而且你可以看看身边的同事,十有八九是不懂线程的异步设计机制的,只知道简单地函数调用概念,只以为主线程(例如上面的 x 任务hi行)在那里”阻塞“着。
  • 打赏
  • 举报
回复
所谓的“下面包含几个子线程”,看这个描述,很可能就是你是只知道那种“阻塞"的思路。根本不理解异步编程设计的本质流程。这个需要重新理解。
  • 打赏
  • 举报
回复
我在帖子 https://bbs.csdn.net/topics/392469590第 65 楼写了一个 demo 程序。你可以看到,异步方法 test 中,可以在 4 个 异步任务执行完毕之后来判断是否全都成功,如果不成功,首先异步调用 4 个委托,等委托全都执行完毕之后再抛出 test 任务执行异常信息。 要说明地是,我觉得纠结“线程”这个字眼儿对于许多人来说是一个大坑。其实要学会的设计思维方式是异步思维方式,而不要纠结线程不线程地。你是用 Task 也就是异步思维方式的体现,当 test 方法异步地执行 4 个 Task 时,使用 WaitAll 的时候,返回了一个 Task 对象,使用 await 来异步地“等待”这个 Task 回调,然后执行 await 后边的代码。这就是异步的编程思想。 如果空谈什么“线程”,那么很可能连这里有没有一个所谓的父线程在“阻塞着”都不知道!实际上 Task.WaitAll 是不阻塞的!!!
橘子皮... 2018-11-11
  • 打赏
  • 举报
回复
引用 2 楼 donghaima 的回复:
第一个问题,我用的方法是用一个INT,++1,--1,=0的时候就代表全部都结束了,当然需要Lock()它。 第二个问题,如果是长时间的操作,不建议用界面的定时器!
++1 --1 不能判断子线程是不是全部结束,只能判断主线程
donghaima 2018-11-07
  • 打赏
  • 举报
回复
第一个问题,我用的方法是用一个INT,++1,--1,=0的时候就代表全部都结束了,当然需要Lock()它。 第二个问题,如果是长时间的操作,不建议用界面的定时器!
橘子皮... 2018-11-04
  • 打赏
  • 举报
回复
还有个问题,如果用system.Timer.Timer创建1个定时器,因为他是独立线程,如果定时器内部执行时间大于定时器设置的间隔时间的话,如我想让他不要重入,就是不要到时间立刻创建1个新线程执行定时器内部的代码,而是类似System.Windows.Forms.Timer 必须等上1个timer的内部代码执行全部结束再立刻开始下1个周期的timer执行,应该怎么改?

110,538

社区成员

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

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

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