同步两个线程 [英] Syncronizing two threads
问题描述
我有两个类:一个产生数据,一个产生数据。
作为两个线程运行,第一个类将数据添加到作业队列,
第二个从队列中获取数据。
我的问题是,消费者线程花费大部分时间等待
,以便数据出现在队列中。我如何告诉消费者数据
是否可用,而不在do ...循环中运行无用的圆圈?
提前致谢!
Iason
下面的代码示例:
班级工作
私人o作为新的Generic.Queue(整数) )
Private b As Boolean
Public Property Done()As Boolean
获取
返回o.Count = 0和b
结束获取
设置(ByVal值为布尔值)
b = value
结束集
结束财产
Public Sub Add(ByVal n As Integer)
o.Enqueue(n)
结束子
公共函数提取()为整数
如果o.Count 0那么
返回o .Dequeue
Else
什么都不退货
结束如果
结束功能
结束班级
班级制作人
公共子产品(ByVal o As Object)
Dim q作为乔布斯= CType(o,乔布斯)
For i Integer = 1 to 100
q.Add(i)
Threading.Thread.Sleep(100)
Next
o.Done = True
End Sub
结束班
< br $>
类消费者
Public Sub Comsume(ByVal o As Object)
Dim q As Jobs = CType(o,Jobs)
做的不是q.Done
Debug.Print(q.Fetch)
循环
End Sub
结束班
I have got two classes: One producing data and one consuming data.
Running as two threads, the first class adds data to a job-queue, the
second one fetches data from the queue.
My problem is that the consumer thread spends most of its time waiting
for data to appear on the queue. How can I tell the consumer that data
is available, without running useless circles in an do...loop?
Thanks in advance!
Iason
Code example below:
Class Jobs
Private o As New Generic.Queue(Of Integer)
Private b As Boolean
Public Property Done() As Boolean
Get
Return o.Count = 0 And b
End Get
Set(ByVal value As Boolean)
b = value
End Set
End Property
Public Sub Add(ByVal n As Integer)
o.Enqueue(n)
End Sub
Public Function Fetch() As Integer
If o.Count 0 Then
Return o.Dequeue
Else
Return Nothing
End If
End Function
End Class
Class Producer
Public Sub Produce(ByVal o As Object)
Dim q As Jobs = CType(o, Jobs)
For i As Integer = 1 To 100
q.Add(i)
Threading.Thread.Sleep(100)
Next
o.Done = True
End Sub
End Class
Class Consumer
Public Sub Comsume(ByVal o As Object)
Dim q As Jobs = CType(o, Jobs)
Do While Not q.Done
Debug.Print(q.Fetch)
Loop
End Sub
End Class
推荐答案
如何告诉消费者数据
How can I tell the consumer that data
可用,而不在do ...循环中运行无用的圆圈?
is available, without running useless circles in an do...loop?
为什么不在数据可用时举起活动?
谢谢,
Seth Rowe
Why not just raise an Event when the data is available?
Thanks,
Seth Rowe
" Iason Mavip" < op ***** @ catholic.orgschrieb
"Iason Mavip" <op*****@catholic.orgschrieb
我有两个类:一个产生数据,一个消耗数据。
作为两个线程运行,第一个类将数据添加到作业队列,
第二个从队列中获取数据。
我的问题是消费者线程花费大部分时间
等待数据出现在队列中。我如何告诉消费者
数据是否可用,而不是在
do ...循环中运行无用的圈子?
提前致谢!
Iason
以下代码示例:
班级工作
Private o As New Generic.Queue(Of Integer)
Private b As Boolean
Public Property Done()As Boolean
获取
返回o.Count = 0并且b
结束获取
设置(ByVal值为布尔值)
b =价值
结束套件
结束物业
Public Sub Add(ByVal n As Integer)
o.Enqueue(n)
结束子
公共函数获取()为整数
如果o.Count 0然后
返回o.Dequeue
否则
不返回
结束如果
结束功能
结束班级
班级制作人
公共子产品(ByVal o As对象)
Dim q As Jobs = CType(o,Jobs)
我的整数= 1到100
q.Add(i)
Threading.Thread.Sleep(100)
下一页
o.Done = True
End Sub
结束课程
类消费者
Public Sub Comsume(ByVal o As Object)
Dim q As Jobs = CType( o,乔布斯)
请不要q.Done
Debug.Print(q.Fetch)
循环
结束次级
结束等级
I have got two classes: One producing data and one consuming data.
Running as two threads, the first class adds data to a job-queue,
the second one fetches data from the queue.
My problem is that the consumer thread spends most of its time
waiting for data to appear on the queue. How can I tell the consumer
that data is available, without running useless circles in an
do...loop?
Thanks in advance!
Iason
Code example below:
Class Jobs
Private o As New Generic.Queue(Of Integer)
Private b As Boolean
Public Property Done() As Boolean
Get
Return o.Count = 0 And b
End Get
Set(ByVal value As Boolean)
b = value
End Set
End Property
Public Sub Add(ByVal n As Integer)
o.Enqueue(n)
End Sub
Public Function Fetch() As Integer
If o.Count 0 Then
Return o.Dequeue
Else
Return Nothing
End If
End Function
End Class
Class Producer
Public Sub Produce(ByVal o As Object)
Dim q As Jobs = CType(o, Jobs)
For i As Integer = 1 To 100
q.Add(i)
Threading.Thread.Sleep(100)
Next
o.Done = True
End Sub
End Class
Class Consumer
Public Sub Comsume(ByVal o As Object)
Dim q As Jobs = CType(o, Jobs)
Do While Not q.Done
Debug.Print(q.Fetch)
Loop
End Sub
End Class
首先,强烈建议开关选项严格打开。
未经测试(!)解决方案:
班级工作
公共事件ItemAdded()
公共事件DoneChanged()
私有o作为新的Generic.Queue(整数)
私有b作为布尔
Public Property Done()As Boolean
获取
返回o.Count = 0并且b
结束获取
设置(ByVal值为布尔值)
b =值
RaiseEvent DoneChanged()
结束集
结束物业
Public Sub Add(ByVal n As Integer)
o.Enqueue(n)
RaiseEvent ItemAdded()
End Sub
Public Function Fetch()As Integer
如果o.Count 0那么
返回o.Dequeue
否则
返回0
结束如果
结束功能
结束班级
班级制作人
Public Sub Produce(ByVal q As Jobs)
我的整数= 1到100
SyncLock q
q.Add(i)
结束SyncLock
Threading.Thread.Sleep(100)
下一页
q.Done = True
End Sub
结束班
班级消费者
私人作为新线程.AutoResetEvent(假)
Public Sub Comsume(ByVal q As Jobs)
AddHandler q.ItemAdded,AddressOf OnItemAdded
AddHandler q.DoneChanged,地址OnDoneChanged
请
ARE.WaitOne()
Do to q.Done
昏暗值为整数
SyncLock q
value = q.Fetch
结束SyncLock
调试。打印(value.ToString)
如果值= 0则退出Do
循环
循环直到q.Done
End Sub
Private Sub OnItemAdded()
ARE.Set()
End Sub
Private Sub OnDoneChanged()
ARE.Set()
结束子
结束班
AutoResetEvent是关键。它等待直到队列完成。或者一个项目
已经添加了CPU使用率。
你确定队列永远不会包含0吗?否则,为空队列返回
0是不明确的。我会添加一个Count属性,或者
你可以从通用队列继承。
(顺便说一下,我更喜欢阻止消费者处理队列而不是
在队列中设置一个Done标志,但也许你有理由这样做。
这样。此外,Done属性可以设置为真的是假的
这是没有意义的。)
Armin
First, it''s strongly recommended to switch Option Strict On.
Untested(!) solution:
Class Jobs
Public Event ItemAdded()
Public Event DoneChanged()
Private o As New Generic.Queue(Of Integer)
Private b As Boolean
Public Property Done() As Boolean
Get
Return o.Count = 0 And b
End Get
Set(ByVal value As Boolean)
b = value
RaiseEvent DoneChanged()
End Set
End Property
Public Sub Add(ByVal n As Integer)
o.Enqueue(n)
RaiseEvent ItemAdded()
End Sub
Public Function Fetch() As Integer
If o.Count 0 Then
Return o.Dequeue
Else
Return 0
End If
End Function
End Class
Class Producer
Public Sub Produce(ByVal q As Jobs)
For i As Integer = 1 To 100
SyncLock q
q.Add(i)
End SyncLock
Threading.Thread.Sleep(100)
Next
q.Done = True
End Sub
End Class
Class Consumer
Private ARE As New Threading.AutoResetEvent(False)
Public Sub Comsume(ByVal q As Jobs)
AddHandler q.ItemAdded, AddressOf OnItemAdded
AddHandler q.DoneChanged, AddressOf OnDoneChanged
Do
ARE.WaitOne()
Do Until q.Done
Dim value As Integer
SyncLock q
value = q.Fetch
End SyncLock
Debug.Print(value.ToString)
If value = 0 Then Exit Do
Loop
Loop Until q.Done
End Sub
Private Sub OnItemAdded()
ARE.Set()
End Sub
Private Sub OnDoneChanged()
ARE.Set()
End Sub
End Class
The AutoResetEvent is the key. It waits til the queue is "done" or an item
has been added w/o CPU usage.
Are you sure that the Queue will never contain 0? Otherwise, returning
0 for an empty queue is ambiguous. I would add a Count property, or
you can Inherit from the generic Queue.
(BTW, I''d prefer stopping the Consumer processing the queue instead of
setting a Done flag in a queue, but maybe there''s a reason for you doing it
this way. In addition, the Done property could be set from True to False
which wouldn''t make sense.)
Armin
rowe_newsgroups schrieb :
rowe_newsgroups schrieb:
>我怎样才能告诉消费者数据可用,而不会在do中运行无用的圈子。 ..环?
>How can I tell the consumer that data
is available, without running useless circles in an do...loop?
为什么不在数据可用时举起活动?
Why not just raise an Event when the data is available?
感谢您的建议;我已经考虑过使用一个事件来每次数据可用时
产生一个新的消费者线程。但是为了确保数据的一致性,如果只有一个线程
一次访问数据库,我会感觉好多了 - 我正在处理一个古老的Access
数据库: - /
Thanks for your suggestion; I already thought about using an event to
spawn a new consumer thread each time data becomes available. But to
ensure data consistency I would feel a lot better if only one thread
would access the database at a time - I''m dealing with an archaic Access
database :-/
这篇关于同步两个线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!