我有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不会完成(这不会导致第一次生成BItemStarted中的线程已经完成的情况)吗?

最佳答案

您的代码有点混乱。

如果在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
    });


任务完成。

07-26 04:39