2014-01-21 7 views
1

Я работаю над приложением окон и сражаюсь с очень резкой ошибкой. Предполагается, что приложение запускается на локальном компьютере и обрабатывает запросы из приложения сервера. Клиентское приложение выглядит так:Метод, вызываемый дважды в тот же момент

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() в клиентском приложении. Проблема заключается в том, что клиентское приложение, которое обрабатывает UserEvents, сбой, если метод UserEvent() запускается дважды в течение одной секунды. (На самом деле это не сбой, просто зависающий, пока вы не убьете задачу, попытка поймать не приведет к ошибке)

То, что я пробовал до сих пор, - это делегировать Thread.Sleep() и SafeSomethingToDB() в другой поток. Это не работает, потому что серверное приложение не дожидается завершения протектора. Таким образом, серверное приложение не находит данные в БД, потому что его не ждет 1 секунда ... Такая же проблема возникает, когда я делал это с работниками фона.

Есть ли возможность обрабатывать эти два триггера, которые поступают из одного и того же серверного приложения, в виде параллельного пути одновременно?

Любые предложения очень apreciated

EDIT: Я думаю, что блокировка метод не вызывает приложение для обработки обоих триггеров в то же время. Для того, чтобы сделать этот видимый I'v попытался это:

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

Когда первый запрос вызывает UserEvent() "MessageBox1" появится, чтобы. Если вы нажмете OK, появится сообщение «MessageBox2». Но если UserEvent запускается второй раз, пока «Messagebox2» все еще открыт, «MessageBox1» не появляется. Вместо этого приложение начинает висит. Должен ли «MessageBox1» снова запускаться вторым триггером UserEvent(), когда два триггера действительно обрабатываются одновременно? Таким образом, два триггера не проходят параллельно или я ошибаюсь здесь?

+0

Переместить 'SaveSomethingToDB()' в поток. –

+0

Отредактировано, извините, не было хорошо. Это было делегировано.Но серверное приложение не ждет завершения потока, поэтому оно продолжается до ввода в БД. – colosso

+0

Сбой клиента, если метод 'UserEvent()' запускается дважды в течение одной секунды или когда 'SafeSomethingToDB()' вызывается дважды в течение одной секунды (ИЛИ, когда метод 'SafeSomethingToDB()' вызывается снова до первого вызов вышел)? –

ответ

2

Не зная, почему вы делаете Sleep или что именно SafeSomethingToDB делает и то, что вызывает ваши проблемы, попробуйте синхронизировать вызовы:

private readonly object _lockObject = new object(); 

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

Thaks для ответа. К сожалению, это не работает. Выполнение этого дважды по-прежнему вызывает зависание. Посмотрите на мое редактирование выше :) – colosso

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(); 
    } 
} 
+0

Спасибо за ваш ответ. К сожалению, блокировка doues не работает. Взгляните на мое редактирование выше :) – colosso

+0

Идея блокировки - убедиться, что в критическом разделе работает только один поток, в вашем редактировании это именно то, что ожидается. с тем, что вы показали до сих пор, мы не можем много помочь, вам нужно определить критический раздел и убедиться, что вы синхронизируете между потоками с семафорами или мониторами (то есть блокировку) и не забудьте вынуть любое модальное окно из этого раздела , – Swift

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.

Смежные вопросы