【发布时间】:2021-05-05 14:20:51
【问题描述】:
我遇到了干净地停止线程的问题。我试图将其简化为下面代码的更基本版本,我想知道我的方法是否完全错误。
我的 Form1 带有一堆 UI 元素,需要在 BackgroundCode 运行时进行更新(我在这里运行它,所以它是一个单独的线程,它不会阻止 UI)然后我通过调用 sub 来更新 UI
(Me.Invoke(Sub()
something.property=something
End Sub))
我也在尝试处理一些由外部文件传递给应用程序的错误。我使用了一个计时器来检查文件,如果它存在,我会抓取内容并将其传递给我的 ErrorHandler。这会将错误写入日志文件,将其显示在屏幕上,然后中止后台工作程序,以便程序不会继续运行。我遇到的问题是,通过执行 BackgroundThread.Abort() 操作本身会触发 ErrorHandler。有没有办法让 BackgroundThread 干净地停止?如果该代码中出现其他问题,我希望 BackgroundThread 触发 ErrorHandler。
我想知道如何使用像“ErrorIsRunning”这样的全局布尔值来限制 ErrorHandler 子程序,以便它只能运行一次,但这开始感觉越来越糟糕,我想知道我是否已经走了在这里完全偏离轨道,如果有更好的方法来处理整个事情。
Public Class Form1
Dim BackgroundThread As New Thread(AddressOf BackgroundCode)
Public Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
‘Hide Error Page
ErrorPage.Visible = False
ErrorLabel.Visible = False
‘Start Background Code
BackgroundThread.Start()
End Sub
Private Sub BackgroundCode()
Try
‘<Background code which runs over a number of minutes>
Catch.ex as Exception
ErrorHandler(“Error with BackgroundCode: “ + ex.Message)
End Try
End Sub
Private Sub Timer_Tick(sender As Object, e As EventArgs) Handles Timer.Tick
Dim ErrorFile As String = “C:\MyErrorFile.Err”
Dim ErrorContents As String
If File.Exists(ErrorFile) Then
Timer.Enabled = False
ErrorContents = File.ReadAllText(ErrorFile).Trim()
ErrorHandler(ErrorContents)
End If
End Sub
Public Sub ErrorHandler(ErrorText As String)
WriteLog(“ERROR” + ErrorText)
Me.Invoke(Sub()
Me.ErrorPage.Visible = True
Me.ErrorLabel.Text = ErrorText
End Sub)
BackgroundThread.Abort()
End Sub
End Class
【问题讨论】:
-
这是XY problem吗?
-
不应使用Thread.Abort。它将“杀死”线程,因此您不知道该线程处于什么状态(因此出现异常)让后台线程不时检查一个布尔值并根据该布尔值结束其循环。现在调用 Thread.Abort 的线程应该设置布尔值。
-
System.Threading.CancellationToken/System.Threading.CancellationTokenSource专为此用途而设计。见IsCancellationRequested。另见ThrowIfCancellationRequested。 -
嗨,谢谢你,我最终使用了一个后台工作者,而不是仅仅创建一个线程并将其设置为在后台运行(我不完全确定我理解这里的区别)但它确实允许我利用取消请求。虽然在最后一个操作之后立即结束线程并不是我想要的,但这确实意味着我可以很容易地在代码中放置很多断点。
标签: vb.net multithreading