代码之家  ›  专栏  ›  技术社区  ›  Jess

有没有一个waitone方法基本上先调用reset?

  •  2
  • Jess  · 技术社区  · 15 年前

    我正在使用一个autoreseteevent,在这里可以对一个事件进行多个set调用(异常处理)。有时会调用一个额外的集合,因此当代码对WaitOne事件进行第二次调用时,它会直接通过,因为门已经打开了。

    解决方法是在waitone之前调用reset。是否有更清洁的解决方案,或者这是唯一的方法?示例代码:

    private void DoSomeWork()
    {
        Thread thrd = new Thread(new ThreadStart(DoSomeOtherStuff));
        thrd.Start();
    
        //mEvt.Reset();
        mEvt.WaitOne();
    
        //continue with other stuff
    }
    
    private void DoSomeOtherStuff()
    {
        /* lots of stuff */
    
        mEvt.Set();
    }
    
    private void ExceptionTriggerNeedsToBreakOutOfDoSomeWork()
    {
       mEvt.Set();
    }
    

    处理完异常后,我需要再次调用dosomework,但由于set可能在多个异常(或rethrown异常)中被调用,所以waitone只是通过。

    我的解决方案是总是在waitone之前调用reset。这是适当的解决方案、糟糕的设计,还是有其他类型的事件可以处理这种情况?

    编辑:我刚将注释重置(建议的解决方案)移动到事件旁边。

    2 回复  |  直到 15 年前
        1
  •  2
  •   James King    15 年前

    我担心的是,如果在waitone()之前调用re set(),那么如果从来没有调用set(),那么就有麻烦了。如果调用set(),然后在点击waitone()之前立即点击reset(),则可能会发生这种情况。即使调用了两次set(),也不能保证在两次调用之后都不会调用reset(),因为没有释放机制来阻塞线程。

    理想情况下,您将有一个try..catch..finally块,并在finally块中调用set(),而不会让异常处理分散在方法中。这对你有用吗?

    汉斯是正确的,在这种情况下,多线程是不必要的。我的担心只适用于您真正使用WaitOne()调用进行多线程处理的情况。

    我也担心你不止一次打电话给赛特…这是否意味着当调用第一个集合时,资源真的应该保持锁定?如果您仍然能够再次点击set(),对我来说,这意味着您仍然在执行与共享资源一起工作的代码。在这种情况下,您不希望对waitOne()的调用取消阻止。

    另请注意,来自msdn:

    不能保证对set方法的每个调用都会释放一个线程。如果两个调用之间的距离太近,以至于第二个调用发生在线程释放之前,则只释放一个线程。好像第二个电话没有发生。

    在任何情况下,似乎您的代码要么执行抛出异常的路径,要么运行到完成,但不能同时执行这两个过程。也就是说,您不应该两次调用set()。

        2
  •  4
  •   Hans Passant    15 年前

    这不是真正的问题,waitone()调用会自动重置事件。毕竟,您使用的是AutoResetEvent,而不是ManualResetEvent。这里的关键短语是自动重置。

    看到它在waitone()调用中快速运行也是很正常的。你有一个很好的多核CPU,当你调用start()的时候线程马上就启动了,只需要几微秒就可以完成任务。毫秒,不管怎样,比你眨眼的速度还要快。

    也许更重要的是,这里不需要线程。开始一个,然后等待它完成是毫无意义的。直接调用dosomeotherstufacture()。

    推荐文章