Ожидание ожидания в C # - PullRequest
0 голосов
/ 30 апреля 2011

Как вы реализуете занятое ожидание не совсем неэффективно?Я сталкиваюсь с проблемой, что я могу загружать данные своей модели только по запросу, что означает, что я должен вызывать методы getXYZ () непрерывно.

Это должно происходить недостаточно быстро для пользователяВзаимодействие, но достаточно быстро, что при изменении состояния в графическом интерфейсе модель может быть замечена и новое состояние получено методами getXYZ ().

Мой подход просто:

while (c.hasChanged()) {
   Thread.sleep(500);
}
updateData();

Есть ли лучшие механизмы?

Ответы [ 4 ]

5 голосов
/ 30 апреля 2011

Ваша проблема, кажется, решаема с Threading .

В WPF вы можете сделать:

Thread t = new Thread((ThreadStart)delegate() {
   while (true) {
      Thread.sleep(500);
      if (c.hasChanged())
          Dispatcher.Invoke((Action)delegate() {updateData();});
   }

}).Start();

В WinForms

Thread t = new Thread((ThreadStart)delegate() {
   while (true) {
      Thread.sleep(500);
      // this must derive from Control
      if (c.hasChanged())
          this.Invoke((Action)delegate() {updateData();});
   }

}).Start();

Возможно, отсутствуют параметры для Invoke (который необходим для выполнения кода в вызывающем потоке пользовательского интерфейса), но я пишу это из своего мозга, так что нет смысла в наличии: D

В .NET 4 вы можете использовать TaskFactory.StartNew вместо того, чтобы создавать поток самостоятельно. В .Net <= 4 вы можете использовать <a href="http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx" rel="nofollow"> TreadPool для потока. Однако я напоминаю, что вам нужно, чтобы это было выполнено сразу, потому что вы ожидаете, что оно будет проверяться как можно скорее, и пул потоков не убедит вас в этом (он может быть уже заполнен, но не очень вероятно :-). Только не делайте глупостей, таких как порождение большего количества из них в цикле!

А внутри потока вы должны поставить чек, как

while (!Closing)

чтобы поток мог закончиться, когда вам это нужно, без необходимости прибегать к плохим вещам, таким как t.Abort(); При выходе установите Closing в true и выполните t.Join(), чтобы закрыть поток проверки.

EDIT:

Я забыл сказать, что Closing должен быть свойством bool или логическим значением VOLATILE , а не простым логическим, потому что вы не будете уверены, что поток может когда-либо завершиться (что ж, в случае Вы закрываете приложение, но это хорошая практика, чтобы заставить их закончить по вашей воле). ключевое слово volatile предназначено для предотвращения применения (псевдо) компилятором любых оптимизаций к коду, которые предполагают, что значения переменных не могут изменяться

2 голосов
/ 30 апреля 2011

Если вы проводите опрос из графического интерфейса, используйте таймер (WinForms).

Если это какой-то фоновый процесс, ваш Sleep () может быть меньшим злом.

2 голосов
/ 30 апреля 2011

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

0 голосов
/ 30 апреля 2011

Явное занятое ожидание - зло, и его следует избегать, когда это возможно.

Если вы не можете избежать этого, то создайте свое приложение, используя шаблон проектирования Observer, и зарегистрируйте заинтересованные объекты в объекте, который выполняет опрос при поддержке потока.

Таким образом, у вас есть чистый дизайн, ограничивающий уродливые вещи в одном месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...