-1

I have a producer–consumer multiply task Class. I have a method:

  private async Task Consume(CancellationToken cancellationToken){..}

There is a starting method:

    public void Run()
    {
        var workerCount = Session.GetParameters().GetThreadCount();
        _workers = new List<Task>(workerCount);
        for (var i = 0; i < workerCount; i++)
            _workers.Add(Consume(StopCancellationTokenSource.Token));
        Task.WhenAll(_workers).ContinueWith(_ => DoneEvent);
    }

The problem is that DoneEvent is fired, but subscriber event handler never get executed. The only way that I succeeded to run event handler is where I made the Run method async and added await before Task.WhenAll(..). But then another issue raised. In the method Consume() I have a ManualResetEvent PauseBlock. And when it is reset the main thread waits also.

Thnx in advance.

EDIT: I have managed to do it right (after two days) I have changed a little bit the Run method:

    public async void Run()
    {
        var workerCount = Session.GetParameters().GetThreadCount();
        _workers = new List<Task>(workerCount);
        for (var i = 0; i < workerCount; i++)
            _workers.Add(Task.Run(()=> Consume(StopCancellationTokenSource.Token)));
        await Task.WhenAll(_workers);
        DoneEvent();
    }

Now it is working correctly. Just for info Consumer method :

    private async Task Consume(CancellationToken cancellationToken)
    {
        try
        {
            await Task.Delay(5000, cancellationToken);
            IEngGroup engGroup;
            while (Groups.TryDequeue(out engGroup))
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (!engGroup.IsEnabled || engGroup.Result.Status == ItemRunningStatus.Successful) continue;

                if (engGroup.IsBreak) Pause();
                //if paused wait
                PauseBlock.WaitOne();
                //if stoped throw
                cancellationToken.ThrowIfCancellationRequested();

                var groupRunner = new GroupRunner(cancellationToken, PauseBlock);

                if (engGroup.FireAndForget)
                    groupRunner.RunGroup(engGroup);
                else
                    await groupRunner.RunGroup(engGroup);
            }
            return;
        }
        catch (OperationCanceledException)
        {
            return ;
        }
    }

Thnx to all of you. If you have any suggestion on ow to improve, I would like to see it.

Gintaras
  • 15
  • 2
  • 10

1 Answers1

0

Try this:

Run().ConfigureAwait(false);

public async Task Run()
{
    ...
    await Task.WhenAll(_workers).ContinueWith(_ => DoneEvent);
}

So this will tell the run it doesn't need to return to the current thread again and finish executing on what ever thread it went onto. It won't block the main thread.

But I must warn you, any code ran on the "DoneEvent" will be executed on the other thread, so if you have any code which affects, for example the UI Thread, you will get a Invalid cross-thread access exception.

Adil Z
  • 121
  • 3