Альтернатива в ситуации повторяющейся задачи спроса - PullRequest
0 голосов
/ 04 мая 2018

У меня есть модуль наблюдателя, который заботится о подписках какого-либо реактивного потока, который я создал из Kafka. К сожалению, мне нужно опросить, чтобы получать сообщения от kafka, поэтому мне нужно выделить одну фоновую ветку для этого. Моим первым решением было следующее:

public void Poll()
{
    if (Interlocked.Exchange(ref _state, POLLING) == NOTPOLLING)
    {
        Task.Run(() =>
        {
            while (CurrentSubscriptions.Count != 0)
            {
                _consumer.Poll(TimeSpan.FromSeconds(1));
            }
             _state = NOTPOLLING;
        });
    }
}

Теперь мой рецензент предложил мне Task, потому что у него есть статусы, и его можно проверить, запущены они или нет. Это привело к этому коду:

public void Poll()
{
    // checks for statuses: WaitingForActivation, WaitingToRun, Running
    if (_runningStatuses.Contains(_pollingTask.Status)) return;
    _pollingTask.Start(); // this obviously throws exception once Task already completes and then I want to start it again
}

Задача осталась практически такой же, но проверка изменилась, поскольку теперь моя логика заключается в том, что я хочу начать опрос, когда у меня есть подписки, и прекратить, когда мне не нужно, мне нужно что-то вроде повторно использовать Задача, но так как я не могу, мне интересно, нужно ли мне вернуться к моей первой реализации или есть какой-то другой изящный способ сделать это, которого сейчас мне не хватает?

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Я думаю, что я пошел на компромисс и удалил Interlocked API для MethodImpl(MethodImpl.Options.Synchronized), что позволяет мне иметь простое тело метода без возможной путаницы с кодом Interlocked API для возможного новичка / неопытного парня.

[MethodImpl(MethodImplOptions.Synchronized)]
public void Poll()
{
    if (!_polling)
    {
        _polling = true;
        new Task(() =>
        {
            while (_currentSubscriptions.Count != 0)
            {
                _consumer.Poll(TimeSpan.FromSeconds(1));
            }
            _polling = false;
        }, TaskCreationOptions.LongRunning).Start();
    }
}
0 голосов
/ 07 мая 2018

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

Ваша первая реализация выглядит хорошо. Вы можете использовать ManualResetEventSlim вместо enum и Interlocked.Exchange, но это, по сути, одно и то же ... до тех пор, пока у вас есть только два состояния.

...