在同一时刻调用两次的方法

时间:2014-01-21 13:15:42

标签: c# .net multithreading winforms thread-safety

我正在处理Windows窗体应用程序并且遇到非常严重的错误。应用程序应该在本地计算机上运行,​​并处理来自服务器应用程序的请求。客户端应用程序如下所示:

public Reader mr_obj;

public Form1()
{
    mr_obj = new MyReader.Reader(7137);
    mr_obj.UserEvent += new ReaderEvent(UserEvent);
}

private void UserEvent(UserEvent e, long threadID)
{
   Thread.Sleep(1000);
   SafeSomethingToDB();
}

Reader()对象将客户端应用程序连接到服务器应用程序。因此,在此之后,服务器应用程序能够在客户端应用程序中触发UserEvent()方法。现在的问题是,如果UserEvent()方法在一秒钟内被触发两次,那么处理UserEvents的客户端应用程序就会崩溃。 (它实际上并没有崩溃只是挂起,直到你杀死任务,尝试抓住不会返回错误)

到目前为止我尝试过将Thread.Sleep()和SafeSomethingToDB()委托给另一个线程。这不起作用,因为服务器应用程序不会等到胎面完成。所以服务器应用程序找不到数据库中的数据,因为它不等待1秒...... 当我与后台工作人员一起工作时,会发生同样的问题。

是否有可能同时处理这两个来自同一服务器应用程序的触发器?

任何非常偏见的建议

编辑:我认为锁定方法不会导致应用程序同时处理两个触发器。为了使这个可见我试过这个:

private void UserEventHandler(UserEvent e, long threadID)
        {
            lock (_lockObject)
            {
                MessageBox.Show("Messagebox 1");
                MessageBox.Show("Messagebox 2");
            }
        }

当第一个请求触发UserEvent()时,出现“MessageBox1”。如果按“确定”,则显示“MessageBox2”。但是如果在“Messagebox2”仍然打开时第二次触发UserEvent,则不会出现“MessageBox1”。而不是应用程序开始挂起。当两个触发器真的同时被处理时,是否应该再次触发“MessageBox1”由UserEvent()的第二个触发器触发?所以这两个触发器并不是平行的,也不是我错在这里?

3 个答案:

答案 0 :(得分:2)

如果不知道为什么要执行SleepSafeSomethingToDB究竟是什么以及导致问题的原因,请尝试同步调用:

private readonly object _lockObject = new object();

private void UserEvent(UserEvent e, long threadID)
{
   lock(_lockObject)
   {
       Thread.Sleep(1000);
       SafeSomethingToDB();
   }
}

答案 1 :(得分:2)

我认为用于同步的简单lock对您有用,请尝试此操作

public Reader mr_obj;
private static readonly object sync = new object();
public Form1()
{
    mr_obj = new MyReader.Reader(7137);
    mr_obj.UserEvent += new ReaderEvent(UserEvent);
}

private void UserEvent(UserEvent e, long threadID)
{
   lock(sync)
   {
      SafeSomethingToDB();
   }
}

答案 2 :(得分:0)

在评论中写下,如果在第一次通话结束前第二次调用SafeSomethingToDB(),则会崩溃。换句话说:SafeSomethingToDB()不是可重入的。

你可以做的是使用一个Mutex(代表互斥),它在你的代码中定义了一个“关键部分”,这意味着一个代码只能有一个线程在任何时候执行它。

例如:

private static Mutex mutex = new Mutex();

public void SafeSomethingToDB()
{
    mutex.WaitOne(); // wait until it is safe to enter the critical section

    // Critical section begins here
    DoWorkAndStuff();

    mutex.ReleaseMutex(); // indicate the end of the critical section
}

有关System.Threading.Mutex的详情,请参阅http://msdn.microsoft.com/en-us/library/system.threading.mutex(v=vs.110).aspx