Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在事件处理程序方法中使用Monitor.TryEnter可以吗?_C#_Event Handling_Locking - Fatal编程技术网

C# 在事件处理程序方法中使用Monitor.TryEnter可以吗?

C# 在事件处理程序方法中使用Monitor.TryEnter可以吗?,c#,event-handling,locking,C#,Event Handling,Locking,我有一个经常调用的EventHandler方法,它的主体处理需要一些时间。是否可以通过监视器锁定此处理程序中的操作? 其目的是在locker锁定对象的同时,跳过对象的其他事件和处理 public void MyEventHandler(object sender, EventArgs e) { if (!Monitor.TryEnter(locker)) return; // skipping meanwhile processing // do some stuff here Monit

我有一个经常调用的EventHandler方法,它的主体处理需要一些时间。是否可以通过监视器锁定此处理程序中的操作? 其目的是在locker锁定对象的同时,跳过对象的其他事件和处理

public void MyEventHandler(object sender, EventArgs e) 
{
if (!Monitor.TryEnter(locker)) return; // skipping meanwhile processing

// do some stuff here

Monitor.Exit(locker)
}

看起来这样会更干净/性能更好

  • (a) 防止引发事件
  • (b) 使用条件变量

无论如何,始终将Monitor.Exit放在finally块中

这样看起来会更干净/性能更好

  • (a) 防止引发事件
  • (b) 使用条件变量

无论如何,始终将监视器.Exit放在finally块中

这并不可怕,只要:

  • 您正在后台线程上执行此操作(或者,在这一点上,您没有在事件处理线程上执行此操作)
  • 您正在同步对
    //执行代码所需操作的所有访问
  • try
    /
    finally
    中,将
    TryEnter
    之后的所有内容包装成一个
    文件,如下所示:

如果您能够完全防止触发事件(从而避免启动线程而可能什么都不做——当然,因为您没有在事件处理线程上执行这种耗时的处理……),那就更好了

或者,如果您真的不需要在整个持续时间内锁定(也就是说,如果事件处理程序不会执行任何需要与其他代码同步的操作),您可以锁定足够长的时间来设置标志,如

private Object condition_lock = new Object();
private bool handlingEvent = false;

public void MyEventHandler(object sender, EventArgs e)
{
    lock (condition_lock)
    {
        if (handlingEvent) return;
        handlingEvent = true;
    }
    try
    {
        // do some stuff here
    }
    finally
    {
        handlingEvent = false;
    }
}

这并不可怕,只要:

  • 您正在后台线程上执行此操作(或者,在这一点上,您没有在事件处理线程上执行此操作)
  • 您正在同步对
    //执行代码所需操作的所有访问
  • try
    /
    finally
    中,将
    TryEnter
    之后的所有内容包装成一个
    文件,如下所示:

如果您能够完全防止触发事件(从而避免启动线程而可能什么都不做——当然,因为您没有在事件处理线程上执行这种耗时的处理……),那就更好了

或者,如果您真的不需要在整个持续时间内锁定(也就是说,如果事件处理程序不会执行任何需要与其他代码同步的操作),您可以锁定足够长的时间来设置标志,如

private Object condition_lock = new Object();
private bool handlingEvent = false;

public void MyEventHandler(object sender, EventArgs e)
{
    lock (condition_lock)
    {
        if (handlingEvent) return;
        handlingEvent = true;
    }
    try
    {
        // do some stuff here
    }
    finally
    {
        handlingEvent = false;
    }
}

+最后一个区块为1。但是,如果有多个事件处理程序可以访问的资源或其他内容,则ad(a)阻止引发事件:无法直接防止触发事件方法,因为eventhandler是从专有DLL调用的@村民迪奥特:嗯,有些资源可以访问,但只能用于阅读。最后一个区块+1。但是,如果有多个事件处理程序可以访问的资源或其他内容,则ad(a)阻止引发事件:无法直接防止触发事件方法,因为eventhandler是从专有DLL调用的@VillageDiot:嗯,有一些资源可以访问,但只能用于阅读。好主意,因为EventHandler是从后台线程生成的-我还没有意识到应该使用try-finally块。我想知道我是否可以这样做。我来测试一下。无法直接防止激发事件方法,因为eventhandler是从专有DLL调用的。但是,我可以通过-=MyEventHandler before Monitor.TryEnter和+=after Monitor.Exit删除它吗?可以想象,如果您有触发事件的对象的引用。但您可能希望在锁定后和解锁前立即执行此操作。此时,您可以保证(1)当前线程是处理事件的线程(因此是负责恢复事件处理程序的线程),并且(2)事件处理程序仍然存在。我假设同时发生两个事件的可能性很低,但即使发生了,只要所有事件处理工作(包括删除/恢复处理程序)都完成,也不会引起问题问题是我发现EvnetHandler经常从后台线程触发,同时它正在处理它的主体,它再次被调用并导致问题。我不想排队参加其他活动,或者别的什么。我只想跳过它们——所以在一个事件的处理完成之前,其他事件对我来说并不重要。那么,这不是问题。获得锁后,移除事件处理程序的委托。处理事件,然后在完成后重新添加代理(在解锁前的
finally
块中)。应该防止事件处理程序在完成之前被调用。但是,如果您发现您无法做到这一点,那么上面的任何一个示例都至少可以防止事件处理程序同时运行两次。好主意,因为事件处理程序是从后台线程引发的-我还没有意识到应该使用try-finally块。我想知道我是否可以这样做。我来测试一下。无法直接防止激发事件方法,因为eventhandler是从专有DLL调用的。但是,我可以通过-=MyEventHandler before Monitor.TryEnter和+=after Monitor.Exit删除它吗?可以想象,如果您有触发事件的对象的引用。但您可能希望在锁定后和解锁前立即执行此操作。此时,您可以保证(1)当前线程是处理事件的线程(因此是负责恢复事件处理程序的线程),并且(2)事件处理程序仍然存在。我假设同时发生两个事件的可能性很低,但即使发生了,只要所有事件处理内容(包括删除/恢复处理程序)都在关键部分内,也不会引起问题