如何使用此代码处理多线程 [英] How do I get this code to work with multi threading
问题描述
我正在为我们的仓库建立KPI评分板,我遇到了以下问题。
我有一个名为order tile的自定义控件,其代码如下:
I am building a KPI score board for our warehouse and i have run into the following issue.
I have a custom control called order tile that has the following code:
Public Class OrderTile
Private _BorderBoxColor As Color
Public Property BorderBoxColor() As Color
Get
Return _BorderBoxColor
End Get
Set
_BorderBoxColor = Value
ChangeBackColor_Threadsafe(_BorderBoxColor)
End Set
End Property
Private _SaleOrder As String
Public Property SalesOrder() As String
Get
Return _SaleOrder
End Get
Set
_SaleOrder = Value
UpdateText_Threadsafe(lblSODS, _SaleOrder)
End Set
End Property
Private _Customer As String
Public Property Customer() As String
Get
Return _Customer
End Get
Set
_Customer = Value
UpdateText_Threadsafe(lblCustomer, _Customer)
End Set
End Property
Private _SalesValue As String
Public Property SalesValue() As String
Get
Return _SalesValue
End Get
Set
_SalesValue = Value
UpdateText_Threadsafe(lblValue, _SalesValue)
End Set
End Property
Private _CountdownTime As TimeSpan
Public Property CountDownTime() As TimeSpan
Get
Return _CountdownTime
End Get
Set
_CountdownTime = Value
tmrCountdown.Interval = 500
tmrCountdown.Start()
End Set
End Property
Private _TargetDT As Date
Public Property TargetDT() As Date
Get
Return _TargetDT
End Get
Set
_TargetDT = Value
End Set
End Property
Private _Flash As Boolean
Public Property Flash() As Boolean
Get
Return _Flash
End Get
Set
_Flash = Value
If _Flash = False Then
tmrFlashBorder.Stop()
'Me.BackColor = _BorderBoxColor
ChangeBackColor_Threadsafe(_BorderBoxColor)
ElseIf _Flash = True Then
tmrFlashBorder.Start()
End If
End Set
End Property
Private Sub tmrCountdown_Tick(sender As Object, e As EventArgs) Handles tmrCountdown.Tick
Dim ts As TimeSpan = _TargetDT.Subtract(DateTime.Now)
If ts.TotalMilliseconds > 0 Then
'lblCountDownTimer.Text = ts.ToString("mm\:ss")
UpdateText_Threadsafe(lblCountDownTimer, ts.ToString("mm\:ss"))
Else
'lblCountDownTimer.Text = "00:00"
UpdateText_Threadsafe(lblCountDownTimer, "00:00")
tmrCountdown.Stop()
End If
End Sub
Private Sub tmrFlashBorder_Tick(sender As Object, e As EventArgs) Handles tmrFlashBorder.Tick
If Me.BackColor = Color.White Then
Me.BackColor = _BorderBoxColor
ElseIf Me.BackColor = _BorderBoxColor Then
Me.BackColor = Color.White
End If
End Sub
Delegate Sub UpdateText_Delegate(ByVal Lable As DevExpress.XtraEditors.LabelControl, ByVal text As String)
Private Sub UpdateText_Threadsafe(ByVal Lable As DevExpress.XtraEditors.LabelControl, ByVal text As String)
If Lable.InvokeRequired Then
Dim MyDelegate As New UpdateText_Delegate(AddressOf UpdateText_Threadsafe)
Me.Invoke(MyDelegate, New Object() {Lable, text})
Else
Lable.Text = text
End If
End Sub
Delegate Sub ChangeBackColor_Delegate(ByVal BackColor As Color)
Private Sub ChangeBackColor_Threadsafe(ByVal BackColor As Color)
If Me.InvokeRequired Then
Dim MyDelegate As New ChangeBackColor_Delegate(AddressOf ChangeBackColor_Threadsafe)
Me.Invoke(MyDelegate, New Object() {Me, BackColor})
Else
Me.BackColor = BackColor
End If
End Sub
End Class
这里是代码使用此控件。此代码是从BackGround Worker DoWork中调用的。
and here is the code that uses this Control. this code is call from within a BackGround Worker DoWork.
Private Sub DrawTiles()
Dim XSpace = 368, YSpace = 120, XMax = 3, YMax = 4
OrderTiles.DefaultView.Sort = "ID ASC"
'grpOrderTiles.Controls.Clear()
ClearTiles_Treadsafe(grpOrderTiles)
Dim TC = 0
Dim TileCount As Integer = OrderTiles.Rows.Count
For i = 0 To TileCount - 1
TC = i + 1
Dim NewTile As New FDVICKPIScreenV4.OrderTile
NewTile.Name = "OrderTile" & OrderTiles.Rows(i).Item(ColTileID).ToString
NewTile.SalesOrder = OrderTiles.Rows(i).Item(ColTileSalesOrderNo).ToString
NewTile.Customer = OrderTiles.Rows(i).Item(ColTileCustomer).ToString
NewTile.SalesValue = OrderTiles.Rows(i).Item(ColTileSalesValue).ToString
NewTile.BorderBoxColor = Color.FromName(OrderTiles.Rows(i).Item(ColTileBox).ToString)
NewTile.CountDownTime = TimeSpan.FromMinutes(30)
NewTile.Flash = OrderTiles.Rows(i).Item(ColTileFlash)
NewTile.TargetDT = OrderTiles.Rows(i).Item(ColTileTargetDT)
If TC = 1 Then
NewTile.Location = New Point(13, 34)
ElseIf TC > 1 AndAlso TC <= 5 Then
NewTile.Location = New Point(13 + XSpace * i, 34) '34 + YSpace * i
ElseIf TC > 5 AndAlso TC <= 10 Then
NewTile.Location = New Point(13 + XSpace * (i - 5), 154)
ElseIf TC > 10 AndAlso TC <= 15 Then
NewTile.Location = New Point(13 + XSpace * (i - 10), 274)
ElseIf TC > 15 AndAlso TC <= 20 Then
NewTile.Location = New Point(13 + XSpace * (i - 15), 394)
End If
AddTile_Treadsafe(grpOrderTiles, NewTile)
Next
End Sub
当我在同一个线程上调用它时,代码运行正常但是当我从BackGround调用它时当我得到Exception User-Unhandled System.NullReferenceException:'对象引用没有设置为对象的实例。'时,
The code runs fine when i call it all on the same thread but when i call it from the BackGround Worker that is when I get "Exception User-Unhandled System.NullReferenceException: 'Object reference not set to an instance of an object.' on the
Dim NewTile As FDVICKPIScreenV4.OrderTile
在DrawTiles Sub中。
我尝试了什么:
我试图实现SyncLock但是我们已经能够实现这一点。我只是不太了解多线程来解决这个问题。
非常感谢所有帮助。
in the DrawTiles Sub.
What I have tried:
I have tried to implement SyncLock but haven been able to get this to work. I just don't know enough about multi threading to resolve this one.
All help is very appreciated.
推荐答案
您滥用了BackgroundWorker的UI报告功能;你应该使用ReportProgress方法和相关的事件处理程序:
BackgroundWorker.ReportProgress方法(System.ComponentModel) [ ^ ]
You've misused the BackgroundWorker's "UI reporting" capabilities; you should be using the "ReportProgress" method and associated event handler:
BackgroundWorker.ReportProgress Method (System.ComponentModel)[^]
这篇关于如何使用此代码处理多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!