2012-01-16 44 views
0

我正在使用C#在ASP.NET中开发一个网页。monitor.enter(锁)问题

许多用户可以同时访问该页面。

按钮单击我正在调用一个具有临界区域的功能。

我已经把这些代码在

try 
{ 
    moniter.enter(lock)   
    salbapi.Sislemcu_Epayroll_Salffs_Bapi(Saljv_str, "N", out messdata, ref Saljv_table); 
} 
catch(Exception e) 
{ 
} 
finally 
{ 
    moniter.exit(lock). 
} 

如果2个用户正在访问在同一时间的功能现在假设。

生成的处理消息被交换或不交换(错误消息显示给用户)。

它不应该发生。

+0

你确定这个代码在一个工作进程中运行?如果没有,你可以创建你想要的所有监视器,但它们不会跨进程同步。 – 2012-01-16 13:23:24

+0

@kumar如果其中一个答案是您要求的答案,那么将其标记为好的形式。 – 2012-01-17 08:38:52

回答

0

你问这是否是线程安全的?如果所有线程都具有锁定变量的可见性,那么是的。

如果一个线程调用了方法并获得了锁,则将会强制另一个线程通过Monitor.Enter等待,直到第一个线程调用Monitor.Exit

0
lock(Application["Lock"]) 
{ 
    salbapi.Sislemcu_Epayroll_Salffs_Bapi(Saljv_str, "N", out messdata, ref  Saljv_table); 
} 

这确保了关键代码在应用程序内一次只能执行一次,无论有多少个同时发生的页面请求。我建议初始化Application["Lock"]在Global.asax中上的Application_Start:

public class Global : System.Web.HttpApplication 
{ 
    protected void Application_Start(object sender, EventArgs e)   
    { 
     Application["Lock"] = new object(); 
    } 

    //other handlers 
} 

我也建议你拿出的VAR一个更好的名字,使其清楚其锁定,并没有在其他地方重复使用死锁的风险。

+0

我用它,但锁内的代码多执行一次' – 2012-01-16 12:02:17

+0

请参阅编辑。您需要使用在页面实例之间共享的锁定对象。记住页面的每个请求都会生成给定页面类的新实例,因此不会在请求之间共享具有类作用域的锁变量。 – 2012-01-16 13:11:44

0

简答Tudor是正确的。长答案:

moniter.enter对于这个逻辑有点低级别。尝试使用lock语句,它是'monitor.enter()的糖;最后尝试{...}(显示器退出)'。此外,捕食和吃异常是非常糟糕的形式;让异常泡沫,因此它被报告。

我会做类似

class Foo 
    { 
    static object synch = new object(); 

    void TheMethod() 
    { 
     lock (synch) 
     { 
      salbapi.Sislemcu_Epayroll_Salffs_Bapi(...); 
     } 
    } 

}

+0

这将在页面事件处理程序的上下文中失败,因为同步是一个类级别的var,我们需要使用应用程序级别var(或定义一个单例,效果相同),以满足要求。 – 2012-01-16 13:15:30

+0

迈尔斯是正确的。我的意思是使它静止。 – 2012-01-16 18:58:47

+0

@RichardSchneider它为我工作,但现在的问题是当2个用户正在访问这个。第二个用户等到第一个完成,当两个完成时,第一个用户的结果显示为第二个,反之亦然......不知道为什么这是开发? – 2012-01-18 03:55:34