C#线程问题与的AutoResetEvent [英] C# Threading issue with AutoResetEvent

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

问题描述

如何正确同步呢?目前,它是可能的的SetData 终止后, e.WaitOne()已完成所谓的 D 可能已被设置为另一个值。我试图插入锁,但它导致陷入僵持。

How to properly synchronize this? At the moment it is possible that SetData is called after e.WaitOne() has completed so d could be already set to another value. I tried to insert locks but it resulted into a deadlock.

AutoResetEvent e = new AutoResetEvent(false);

public SetData(MyData d)
{
   this.d=d;
   e.Set();    // notify that new data is available
}

// This runs in separate thread and waits for d to be set to a new value
void Runner() 
{    
   while (true)
   {
      e.WaitOne();  // waits for new data to process
      DoLongOperationWith_d(d);
   }
}



请问最好的解决办法是引入一个新的布尔变量即在的SetData 设置为true,并在 DoLongOperationWith_d dataAlreadyBeenSetAndWaitingToBeProcessed

Will the best solution be to introduce a new boolean variable dataAlreadyBeenSetAndWaitingToBeProcessed that is set in SetData to true and at the end of DoLongOperationWith_d it could be set to true, so if SetData is called with this variable set to true it could just return?

推荐答案

这是未经测试,而是一种优雅的方式与基于.NET元要做到这一点:

This is untested, but is an elegant way to do this with the .net based primitives:

class Processor<T> {
    Action<T> action;
    Queue<T> queue = new Queue<T>();

    public Processor(Action<T> action) {
        this.action = action;
        new Thread(new ThreadStart(ThreadProc)).Start();
    }

    public void Queue(T data) {
        lock (queue) {
            queue.Enqueue(data);
            Monitor.Pulse(queue); 
        }            
    }

    void ThreadProc() {
        Monitor.Enter(queue);
        Queue<T> copy;

        while (true) {                 
            if (queue.Count == 0) {
                Monitor.Wait(queue);
            }

            copy = new Queue<T>(queue);
            queue.Clear();
            Monitor.Exit(queue);

            foreach (var item in copy) {
                action(item); 
            }

            Monitor.Enter(queue); 
        }
    }
}



程序范例:

Example program:

class Program {

    static void Main(string[] args) {

        Processor<int> p = new Processor<int>((data) => { Console.WriteLine(data);  });
        p.Queue(1);
        p.Queue(2); 

        Console.Read();

        p.Queue(3);
    }
}

这是一个非队列版本,队列版本可优选:

This is a non-queue version, a queue version may be preferred:

object sync = new object(); 
AutoResetEvent e = new AutoResetEvent(false);
bool pending = false; 

public SetData(MyData d)
{
   lock(sync) 
   {
      if (pending) throw(new CanNotSetDataException()); 

      this.d=d;
      pending = true;
   }

   e.Set();    // notify that new data is available
}

void Runner() // this runs in separate thread and waits for d to be set to a new value
{

     while (true)
     {

             e.WaitOne();  // waits for new data to process
             DoLongOperationWith_d(d);
             lock(sync) 
             {
                pending = false; 
             }
     }
}

这篇关于C#线程问题与的AutoResetEvent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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