Использование общих делегатов для перехвата асинхронного вызова - PullRequest
2 голосов
/ 03 февраля 2011

У меня есть несколько фрагментов кода, подобных следующему:

void GetPerson(Action<PersonView, Exception> callback);

...

IsBusy = true;
_personRequested = true;
_service.GetPerson((person, error) => 
{
 if (error != null)
  {
    return;
  }
  _person = person;
  _personLoaded = true;
  IsBusy = false;
});

Проблема, с которой я работаю, состоит в том, что данный класс может запускать несколько различных асинхронных вызовов, и свойство IsBusy должно быть«умный», чтобы не отключаться только потому, что вызов «А» завершен, но «В» и «С» все еще ожидают.Следовательно, _personRequested и _personLoaded booleans.Тем не менее, я хотел бы перейти к чему-то более общему, но немного не уверен, как поступить.

Сначала я задумался о настройке функции, которая принимает приведенный выше код в качестве делегата, но я продолжаюувязнуть в странном синтаксисе.Мне бы хотелось, чтобы функционал был таким, чтобы я просто обернул все это и передал его своей функции как анонимному методу, а затем в этой функции и обратном вызове я бы обработал занятые состояния моих классов.

Любая помощь приветствуется, спасибо.

Ответы [ 3 ]

3 голосов
/ 03 февраля 2011

Если все, что вы ищете, это индикатор того, что что-то используется, вам, вероятно, лучше использовать счетчик, а не простой логический флаг. Затем вы можете использовать Interlocked.Increment и Interlocked.Decrement для изменения значения в поточно-ориентированном режиме.

Объявите это на уровне класса:

private volatile int isBusyCounter;

Interlocked.Increment(ref isBusyCounter);
_personRequested = true;
_service.GetPerson((person, error) => 
{
 if (error != null)
  {
    return;
  }
  _person = person;
  _personLoaded = true;
  Interlocked.Decrement(ref isBusyCounter);
});

(Использование Interlocked необходимо, поскольку вы изменяете значение в нескольких потоках, и это гарантирует, что обновления не конфликтуют друг с другом; нас не волнует порядок, так как вы закончите с одним и тем же значением, случается ли одно первым или другим)

Тогда, вместо того, чтобы просто проверять IsBusy, проверьте IsBusy > 0. Переменная должна быть volatile, чтобы последующие чтения переменной в методе не оптимизировались (другими словами, если вы проверяете это условие в цикле или несколько раз в рамках данной функции, то мы помещаем volatile, чтобы гарантировать, что значение проверяется каждый раз, а не кэшируется локально).

1 голос
/ 03 февраля 2011

Я бы, вероятно, подумал, что булевы логики и их логика должны быть объединены в "конечный автомат" или что-то подобное: http://www.codeproject.com/KB/architecture/statepatterncsharp.aspx

0 голосов
/ 03 февраля 2011

используйте счетчик и приращение для каждого начала и уменьшения в конце, убедитесь, что вы делаете его безопасным для гонки

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