简体   繁体   English

多线程故障

[英]Multi-Threading Glitch

I have a program that uses a label called Valve and a textbox called Variable 我有一个程序使用名为Valve的标签和名为Variable的文本框

The gist is that if the Variable = 0 then the label colour is gray, If the Variable = 1 then the label uses a thread which flashes between gray and red. 要点是,如果Variable = 0则标签颜色为灰色;如果Variable = 1则标签使用的线程在灰色和红色之间闪烁。

This works almost perfectly apart from if changing between the two values very quickly (entering 0 then deleting it then entering 1, and so on) Then the thread speed increases (as if it is multi-threading). 这与在两个值之间快速更改(输入0然后将其删除然后输入1,依此类推)之间的变化非常完美,然后线程速度增加了(就像多线程一样)。

The strange thing is that if swapping between the values 0 & 1 slowly (every 2 seconds +), then it doesn't increase the blinking speed (this is what the program needs to do) 奇怪的是,如果缓慢地在值0和1之间交换(每2秒+),那么它不会增加闪烁速度(这是程序需要做的)

This is expanded code from the following question: vb.net multi threading 这是来自以下问题的扩展代码: vb.net多线程

Note: This is just a VB.NET conversion from my project on VisiWin.NET. 注意:这只是我在VisiWin.NET上的项目的VB.NET转换。 In this example the TextBox Variable will be an actual variable read from a PLC and the label Valve will be triangles representing a process solenoid from a process flowsheet mimic. 在此示例中,TextBox Variable将是从PLC读取的实际变量,而Valve标记将是代表过程流程图模拟中的过程螺线管的三角形。 Every solenoid will be controlled by different variables. 每个螺线管将由不同的变量控制。

Imports Microsoft.VisualBasic
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Threading
Imports System.Diagnostics

Public Class Form1

Private _flash As Boolean = False

Private Sub Variable1_TextChanged(sender As System.Object, e As System.EventArgs) Handles Variable.TextChanged


    If Variable.Text = "1" And Not _flash Then
        _flash = True
        Dim FlashThread As New Thread(New ThreadStart(AddressOf FlashLabel))
        FlashThread.Start()
    End If

    If Variable.Text = "0" Then
        _flash = False
        Valve.ForeColor = Color.Gray
    End If

End Sub


Private Sub FlashLabel()

    Dim _Color As Color = Color.Gray
    While _flash

        If Valve.ForeColor = _Color Then
            Valve.ForeColor = Color.Red
        Else
            Valve.ForeColor = Color.Gray
        End If
        System.Threading.Thread.Sleep(2000)

    End While

End Sub

End Class

What's happening here is that your first flashing thread is still running, it's just in the two second sleep phase. 这里发生的是您的第一个刷新线程仍在运行,仅在第二个睡眠阶段。 Your value changes to 0, it doesn't break out of the loop because it's asleep and then the variable changes back to 1 again, the thread wakes up and carries on, by which time you have spawned another thread doing the exact same thing, so it appears as if the thread is going faster. 您的值更改为0,因为它处于睡眠状态,所以不会中断循环,然后变量又变回1,该线程唤醒并继续运行,到那时您已经生成了另一个完全相同的线程,因此看起来好像线程运行得更快。

I would suggest changing this to a timer instead, as you can stop the timer when the variable is 0, and then restart it when it is 1: 我建议将其改为计时器,因为您可以在变量为0时停止计时器,然后在变量为1时重新启动计时器:

Imports Microsoft.VisualBasic
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Threading
Imports System.Diagnostics

Public Class Form1

Private _timer As New System.Windows.Forms.Timer()

Private Sub Variable1_TextChanged(sender As System.Object, e As System.EventArgs) Handles Variable.TextChanged


    If Variable.Text = "1" And Not _flash Then
        _flash = True
        _timer.Interval = 2000
        _timer.Enabled = True
        _timer.Start()
    End If

    If Variable.Text = "0" Then
        _flash = False
        _timer.Stop()
        _timer.Enabled = False
        Valve.ForeColor = Color.Gray
    End If

End Sub


Private Sub FlashLabel() Handles _timer.Tick

    Dim _Color As Color = Color.Gray

    If Valve.ForeColor = _Color Then
        Valve.ForeColor = Color.Red
    Else
        Valve.ForeColor = Color.Gray
    End If

End Sub

End Class

Docs for Timer: http://msdn.microsoft.com/en-gb/library/system.windows.forms.timer.aspx 计时器文档: http//msdn.microsoft.com/en-gb/library/system.windows.forms.timer.aspx

Alternatively, you could store the thread in a field and terminate it when your variable is set to 0: 另外,您可以将线程存储在字段中,并在变量设置为0时终止该线程:

Imports Microsoft.VisualBasic
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Threading
Imports System.Diagnostics

Public Class Form1

Private _flash As Boolean = False
Private _flashThread as Thread

Private Sub Variable1_TextChanged(sender As System.Object, e As System.EventArgs) Handles Variable.TextChanged


    If Variable.Text = "1" And Not _flash Then
        _flash = True
        _flashThread As New Thread(New ThreadStart(AddressOf FlashLabel))
        _flashThread.Start()
    End If

    If Variable.Text = "0" Then
        _flash = False
        _flashThread.Abort()
        Valve.ForeColor = Color.Gray
    End If

End Sub


Private Sub FlashLabel()

    Dim _Color As Color = Color.Gray
    While _flash

        If Valve.ForeColor = _Color Then
            Valve.ForeColor = Color.Red
        Else
            Valve.ForeColor = Color.Gray
        End If
        System.Threading.Thread.Sleep(2000)

    End While

End Sub

End Class

See http://msdn.microsoft.com/en-GB/library/ty8d3wta.aspx for notes on aborting threads, although I don't think any of this really applies to you, if it doesn't abort the thread during it's sleeping time, it should abort before the next iteration of the loop. 有关中止线程的说明,请参见http://msdn.microsoft.com/zh-CN/library/ty8d3wta.aspx ,尽管我认为这其中的任何一项对您都不适用,但前提是它在中止线程期间不会中止线程睡眠时间,它应该在循环的下一次迭代之前中止。

The problem is the following: 问题如下:

  1. You enter 1, _flash is False : The thread is started, changes the color and sleeps 2 seconds 您输入1, _flashFalse :线程启动,更改颜色并休眠2秒钟
  2. You enter 0 quickly after entering 1, _flash is True : _flash will be set to False . 输入1后迅速输入0, _flashTrue_flash将设置为False
  3. You enter 1 quickly after entering 0, _flash is False again: A new thread is started. 输入0后立即输入1, _flash再次为False :启动新线程。

Now, if steps 2 and 3 happen while the first thread sleeps, you have two running threads. 现在,如果第一个线程休眠时发生了步骤2和3,则您有两个正在运行的线程。 After the first thread is finished sleeping, it will see that _flash is True and will continue running. 在第一个线程完成睡眠之后,它将看到_flashTrue并将继续运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM