如何在C#中的多个线程中处理一次信号

时间:2011-04-27 04:13:49

标签: c# multithreading

在C#中,我有多个对象,每个对象都有自己的线程,可以根据外部信号执行操作。所有对象都保留所有其他对象的列表 我需要在单线程中仅在单个对象中执行的信号。该信号将删除所有物体,因此多个信号不会到达同一物体 很可能信号将在同一时间到达所有信号,但可能会有晚信号。由于信号将导致所有这些信号遭到破坏而不会被传递给被破坏的信号,因此可以忽略延迟 我虽然做lock(this)然后锁定列表中的每个对象,但我不知道如何在不为其创建范围的情况下执行锁定(意味着手动解锁,而不是在锁定范围结束时)。
另外一个问题是,如果一个人已经开始锁定而另一个人试图锁定它,它就会等待而不是忽略它 此外,我无法控制Thread个对象,即使有办法检索它们,Thread对象上的任何触摸都可能会使应用程序崩溃。暂停所有其他线程的答案将无效 那么如何让信号由一个物体作用并被其余物体忽略呢?

3 个答案:

答案 0 :(得分:1)

您可以拥有一个父线程来跟踪已处理的内容。当线程收到新信号时,您可以询问父母是否已经处理了该信号。如果没有,请处理它,父母将其他人锁定。

您还可以查看使用消息队列,每个信号只能由一个线程获取。

答案 1 :(得分:1)

我想我理解现在发生了什么,但如果这是错误的话,请纠正我:

  • 大概所有对象都属于同一类型
  • 对象列表是静态的(如果没有,那么考虑更有效率)
  • 任何对象都可以接收信号,但只有一个会处理它。

因此,如果我们假设您的每个对象都有接收信号的方法,那么我认为这可能是一个不错的设计:

public class Thing
{
    private static volatile bool _tooLate = false;
    private static List<Thing> _theWorld; // contains everything
    private static readonly object _sync = new object();

    public Thing(){/*...*/}

    // a static method to process the signal
    public static void ProcessSignal(Signal signal)
    {
        // make sure you're not late to the party
        if(signal == signal.DestroyTheWorld && !_tooLate)
        {
            // You won't destroy the world yet... but you'll give it a shot!
            BringAboutTheDestruction();
        }
    }

    // a static method to bring about the destruction of the world! MUAHAHAHAHA
    public static void BringAboutTheDestruction()
    {
        // you might not be late for the party, 
        // but you still have to get past the doorman
        lock(_sync)
        {
            // you finally got in, but you might get kicked out!
            if(!_tooLate)
            {
                // Apocalypse now!!! There is no turning back
                foreach(Thing t in _theWorld)
                {
                    t.Destroy();
                }
                _theWorld.Clear();
            }
            _tooLate = true;
        }
    }
}

答案 2 :(得分:1)

您始终可以使用EventWaitHandle类。每个线程都有两个,一个是线程需要做某事,另一个是关闭所有线程。第一个是线程本地的,第二个是全局的:

void CreateThreads ()
{
   global_event = new EventWaitHandle (false, EventResetMode.AutoReset);

   for each thread to create
   {
     create thread a pass the global_event object
   }
}

void ThreadProc (EventWaitHandle global_event)
{
  create local_event; // this is set when the thread needs to do something

  bool quit = false;

  while (!quit)
  {
    switch (EventWaitHandle.WaitAny (new WaitHandle [] { global_event, local_event })
    {
    case 0: // global 
      shut down other threads
      quit = true;
      break;

    case 1: // local
      do local signal processing
      break;
    }
  }
}

EventResetMode.AutoReset标志表示只会释放等待事件的所有线程中的一个。当然,你无法预测哪一个。