kuskmen
kuskmen

Reputation: 3775

Alternative in a situation of recurring Task demand

I have observer module which takes care of subscriptions of some reactive stream I have created from Kafka. Sadly I need to Poll in order to receive messages from kafka, so I need to dedicate one background thread for that. My first solution was this one:

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

Now my reviewer suggested that I should Task because it have statuses and can be checked if they are running or not. This led to this code:

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
}

Task remained pretty much the same but check changed, now since my logic is that I want to start polling when I have subscriptions and stop when I don't I need to sort of re-use the Task, but since I can't I am wondering do I need to go back to my first implementation or is there any other neat way of doing this that right now I am missing?

Upvotes: 0

Views: 70

Answers (2)

kuskmen
kuskmen

Reputation: 3775

I think I made a compromise and removed Interlocked API for MethodImpl(MethodImpl.Options.Synchronized) it lets me have simple method body without possibly confusing Interlocked API code for eventual newcomer/inexperienced guy.

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

Upvotes: 0

Haukinger
Haukinger

Reputation: 10863

I am wondering do I need to go back to my first implementation or is there any other neat way of doing this that right now I am missing?

Your first implementation looks fine. You might use a ManualResetEventSlim instead of enum and Interlocked.Exchange, but that's essentially the same... as long as you have just two states.

Upvotes: 1

Related Questions