同步两个线程 [英] Syncronizing two threads

查看:74
本文介绍了同步两个线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个类:一个产生数据,一个产生数据。

作为两个线程运行,第一个类将数据添加到作业队列,

第二个从队列中获取数据。


我的问题是,消费者线程花费大部分时间等待
,以便数据出现在队列中。我如何告诉消费者数据

是否可用,而不在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆