我有2节课:
public class A
{
private const int MAXCOUNTER = 100500;
private Thread m_thrd;
public event Action<string> ItemStarted;
public event Action<string> ItemFinished;
private void OnItemStarted(string name)
{
if (ItemStarted != null) ItemStarted(name);
}
private void OnItemFinished(string name)
{
if (ItemFinished != null) ItemFinished(name);
}
public A()
{
m_thrd = new Thread(this.Run);
m_thrd.Start();
}
private void Run()
{
for (int i = 0; i < MAXCOUNTER; i++)
{
OnItemStarted(i.ToString());
// some long term operations
OnItemFinished(i.ToString());
}
}
}
public class B
{
private Thread m_thrd;
private Queue<string> m_data;
public B()
{
m_thrd = new Thread(this.ProcessData);
m_thrd.Start();
}
public void ItemStartedHandler(string str)
{
m_data.Enqueue(str);
}
public void ItemFinishedHandler(string str)
{
if (m_data.Dequeue() != str)
throw new Exception("dequeued element is not the same as finish one!");
}
private void ProcessData()
{
lock (m_data)
{
while (m_data.Count != 0)
{
var item = m_data.Peek();
//make some long term operations on the item
}
}
}
}
我们在代码中还有其他地方
A a = new A();
B b = new B();
a.ItemStarted += b.ItemStartedHandler;
a.ItemFinished += b.ItemFinishedHandler;
因此,如果在
ItemFinished
仍在工作时升高ProcessData()
,会发生什么?我是否应该使用类似
AutoResetEvent
的方法使类A
等待类B
完成ProcessData
?是否有必要在
lock
中使用ProcessData
?用
B
调用类m_thrd = new Thread(this.ProcessData);
的线程可以吗?事情在这里让我感到困惑-在发出任何ProcessData
事件之前ItemStarted
不会完成(这不会导致第一次生成B
时ItemStarted
中的线程已经完成的情况)吗? 最佳答案
您的代码有点混乱。
如果在ItemFinished
完成之前提高了ProcessData()
,则您的第一个问题是竞赛条件。
不用担心使用AutoResetEvent
。简单的事情是锁定对m_data
的每次访问。因此导致下一个查询-是的,锁是必需的,并且在任何地方都是必需的。
但最后一点是最重要的。您需要将每个构造函数更改为.Start()
方法,以便在开始之前有时间进行连接。
但是,即使那样,您的比赛条件仍然很糟糕。
这是您要做的工作。 NuGet“ Rx-Main”将Microsoft的Reactive Framework添加到您的代码中。然后执行以下操作:
var scheduler1 = new EventLoopScheduler();
var scheduler2 = new EventLoopScheduler();
Observable
.Range(0, 100500)
.ObserveOn(scheduler1)
.Do(x => { /* some long term operations */ })
.ObserveOn(scheduler2)
.Subscribe(x =>
{
//make some long term operations on the item
});
任务完成。