多线程故障

时间:2013-02-08 10:23:46

标签: .net vb.net multithreading

我有一个程序使用名为Valve的标签和一个名为Variable的文本框

要点是,如果Variable = 0则标签颜色为灰色, 如果Variable = 1那么标签使用的线程在灰色和红色之间闪烁。

除了非常快速地在两个值之间进行更改(输入0然后删除它然后输入1,依此类推)之外,这几乎完全有效。然后线程速度增加(就好像它是多线程的)。

奇怪的是,如果在0和0之间交换值1缓慢(每2秒+),然后它不会增加闪烁速度(这是程序需要做的)

这是以下问题的扩展代码:vb.net multi threading

注意:这只是我在VisiWin.NET上的项目的VB.NET转换。在此示例中,TextBox Variable将是从PLC读取的实际变量,标签Valve将是表示来自过程流程图模拟的过程电磁阀的三角形。每个电磁阀都由不同的变量控制。

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

2 个答案:

答案 0 :(得分:3)

这里发生的事情是你的第一个闪存线程仍在运行,它只处于两秒钟的睡眠阶段。你的值变为0,它没有突破循环,因为它处于睡眠状态,然后变量再次变回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

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

或者,您可以将线程存储在字段中,并在变量设置为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

有关中止线程的注意事项,请参阅http://msdn.microsoft.com/en-GB/library/ty8d3wta.aspx,虽然我认为这并不适用于您,如果它在休眠期间没有中止线程,它应该在下一次迭代之前中止循环。

答案 1 :(得分:0)

问题如下:

  1. 您输入1,_flashFalse:线程已启动,更改颜色并休眠2秒
  2. 输入1后快速输入0,_flashTrue_flash将设为False
  3. 输入0后快速输入1,再次_flashFalse:启动新线程。
  4. 现在,如果在第一个线程休眠时发生第2步和第3步,则有两个正在运行的线程。在第一个线程完成休眠后,它会看到_flashTrue并将继续运行。