C# 应用程序挂起锁定语句

C# 应用程序挂起锁定语句,c#,compact-framework,C#,Compact Framework,我正在使用c compact framework和vs2008。我面临的是关于锁声明的问题。我的应用程序大部分时间都在工作,但有时仍然挂起 我试过这些 1) Lock(this) 2) lock (Core.Processor.Input.GPSIDInput.gps) 3) Monitor.TryEnter(Core.Processor.Input.GPSIDInput.gps); try{} finally{ Monitor.Exit(this); } 为什么在我使用try-catch-b

我正在使用c compact framework和vs2008。我面临的是关于锁声明的问题。我的应用程序大部分时间都在工作,但有时仍然挂起

我试过这些

1) Lock(this)
2) lock (Core.Processor.Input.GPSIDInput.gps)
3) Monitor.TryEnter(Core.Processor.Input.GPSIDInput.gps);
try{}
finally{ Monitor.Exit(this); }
为什么在我使用try-catch-block时,当锁出现故障时它不会出现

Gps.cs

[DllImport("coredll.dll")]
static extern int CloseHandle(IntPtr hObject);

public void Close()
{
    try
    {
        lock (Core.Processor.Input.GPSIDInput.gps)
        {

            if (newLocationHandle != IntPtr.Zero){
            CloseHandle(newLocationHandle);
            newLocationHandle = IntPtr.Zero;
            }......

        }
    }
    catch (Exception excpt)
    {
    //stack trace
    }
}
GPSIDInput.cs

namespace Core.Processor.Input
{
    public class GPSIDInput
    {
        .......
        public static Gps gps = new Gps();

        public static void CloseGPS()
        {
            gps.Close();
        }
    }
}

锁的工作原理就像一个关键部分。只有一个线程可以“保持锁”。当一个线程执行此操作时,另一个试图保持锁的线程必须等待,直到另一个线程释放它。没有“使锁失败”这样的事情,它只是等待持有它的线程释放它。

锁的工作就像一个关键部分。只有一个线程可以“保持锁”。当一个线程执行此操作时,另一个试图保持锁的线程必须等待,直到另一个线程释放它。没有“使锁失败”这样的事情,它只是等待持有它的线程释放它。

如果您只担心两个线程试图同时释放句柄,那么可以使用以下方法来解决问题:

object closeLockObj = new object();
public void Close()
{
    try
    {
        lock (closeLockObj)
        {

            if (newLocationHandle != IntPtr.Zero){
            CloseHandle(newLocationHandle);
            newLocationHandle = IntPtr.Zero;
            }......

        }
    }
    catch (Exception excpt)
    {
    //stack trace
    }
}

如果其他代码锁定了Core.Processor.Input.GPSIDInput.gps,则可能会导致应用程序挂起。因此,最好使用一个单独的lockObject来解决这个问题,如果您只担心两个线程试图同时释放句柄,那么可以使用如下方法:

object closeLockObj = new object();
public void Close()
{
    try
    {
        lock (closeLockObj)
        {

            if (newLocationHandle != IntPtr.Zero){
            CloseHandle(newLocationHandle);
            newLocationHandle = IntPtr.Zero;
            }......

        }
    }
    catch (Exception excpt)
    {
    //stack trace
    }
}


如果其他代码锁定了Core.Processor.Input.GPSIDInput.gps,则可能会导致应用程序挂起。因此,最好使用单独的lockObject

当锁失败时,您的意思是什么?如果一个线程想要获得锁,而另一个线程已经获得了锁,那么它将阻塞,它不会抛出异常并继续。您的应用程序中有多个线程吗?是否正在获取其他锁?您可能遇到死锁,但问题中的信息不足。设备遇到锁时会挂起。它无法进入锁内。您希望它在多线程模式下工作吗?那么我认为您应该从代码中移除锁。当只有一个线程可以持有锁时,就不需要锁。锁失败是什么意思?如果一个线程想要获得锁,而另一个线程已经获得了锁,那么它将阻塞,它不会抛出异常并继续。您的应用程序中有多个线程吗?是否正在获取其他锁?您可能遇到死锁,但问题中的信息不足。设备遇到锁时会挂起。它无法进入锁内。您希望它在多线程模式下工作吗?那么我认为您应该从代码中移除锁。如果只有一个线程可以持有锁,则不需要该锁。如果需要,请等待。它已经来了。为什么设备会挂起。当操作系统在接收到Instances的新位置时触发事件。另一方面,它是在lockya beiboer时使用的,如果我移除锁,它很可能不会挂起。但是它可能会被操作系统中断,用户操作可能不会发生,这就是我试图锁定它的原因。如果你是说Close方法可能会从多个线程调用,那么我认为@BoeseB的答案应该可以解决这个问题。当您使用lock语句时,您应该使用一个对象实例,就像在他的回答中一样。如果以防万一,请等待。它已经来了。为什么设备会挂起。当操作系统在接收到Instances的新位置时触发事件。另一方面,它是在lockya beiboer时使用的,如果我移除锁,它很可能不会挂起。但是它可能会被操作系统中断,用户操作可能不会发生,这就是我试图锁定它的原因。如果你是说Close方法可能会从多个线程调用,那么我认为@BoeseB的答案应该可以解决这个问题。当你使用lock语句时,你应该使用一个对象实例,就像在他的回答中一样。当OP意味着可以同时从不同线程调用Close方法时,这个答案应该合适。你好Boese&Beiboer。我测试了设备的变化,它正在工作,所以感谢你们。1创建新objectcloseLockObj的原因是什么,为什么我们试图锁定不相关的不同对象。2锁可以是任何虚拟对象,也可以是我正在处理的同一类的对象。请看关于死锁的部分,以获得一个简短的解释,为什么您最好使用一个在您的情况下没有暴露在外部的对象。其他一些代码可能已经请求对Core.Processor.Input.GPSIDInput.gps进行锁,因此您关闭方法无法获得锁定并一直等待外部代码释放锁定。您不是“锁定”该对象,而是将该对象用作锁定的钥匙。编译器实际上生成了对Monitor.Enter的调用,使用对象作为键。这并不是说锁定对象本身被锁定,或者被设置为只读,或者其他什么。第一个获取锁的线程将继续,下一个尝试这样做的线程必须等待锁被释放。我
使用私有对象作为锁密钥是最佳实践,因为这样您就可以确定您是唯一一个将锁定此对象的人。当OP意味着可以同时从不同线程调用Close方法时,这个答案应该合适。您好Boese&Beiboer。我测试了设备的变化,它正在工作,所以感谢你们。1创建新objectcloseLockObj的原因是什么,为什么我们试图锁定不相关的不同对象。2锁可以是任何虚拟对象,也可以是我正在处理的同一类的对象。请看关于死锁的部分,以获得一个简短的解释,为什么您最好使用一个在您的情况下没有暴露在外部的对象。其他一些代码可能已经请求对Core.Processor.Input.GPSIDInput.gps进行锁,因此您关闭方法无法获得锁定并一直等待外部代码释放锁定。您不是“锁定”该对象,而是将该对象用作锁定的钥匙。编译器实际上生成了对Monitor.Enter的调用,使用对象作为键。这并不是说锁定对象本身被锁定,或者被设置为只读,或者其他什么。第一个获取锁的线程将继续,下一个尝试这样做的线程必须等待锁被释放。最好的做法是使用私有对象作为锁定密钥,因为这样您就可以确定您是唯一会锁定此对象的人。