Pregunta

I'm currently working on a small project that use Tasks.Dataflow and I'm a little bit confused about UI notifications. I want to separate my "Pipeline" from the UI in another class called PipelineService, but I'm unable to notify the UI on cancelled operations or data that should be shown up in the UI. How can this be handled in the right manner?

Code:

    private void btnStartPipeline_Click(object sender, EventArgs e)
    {
        btnStartPipeline.Enabled = false;
        btnStopPipeline.Enabled = true;

        cancellationToken = new CancellationTokenSource();

        if (head == null)
        {
            head = pipeline.SearchPipeline();        
        }

        head.Post(AppDirectoryNames.STORE_PATH);
    }

    private void btnStopPipeline_Click(object sender, EventArgs e)
    {
        cancellationToken.Cancel();
    } 

This methods related to Form1.cs. head is type of ITargetBlock<string>.

    public ITargetBlock<string> SearchPipeline()
    { 
        var search = new TransformBlock<string, IEnumerable<FileInfo>>(path =>
            {
                try
                {
                    return Search(path);
                }
                catch (OperationCanceledException)
                {
                    return Enumerable.Empty<FileInfo>();
                }
            });

        var move = new ActionBlock<IEnumerable<FileInfo>>(files =>
            {
                try
                {
                    Move(files);
                }
                catch (OperationCanceledException ex)
                {
                    throw ex;
                }
            });

        var operationCancelled = new ActionBlock<object>(delegate
            {

                form.Invoke(form._update);
            },
            new ExecutionDataflowBlockOptions
            {
                TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
            });

        search.LinkTo(move);

        search.LinkTo(operationCancelled);

        return search;
    }

Invoke don't take effect with delegate methods. What am I doing wrong here?

¿Fue útil?

Solución

At first, I din't understand why you think your code should work. The way you set up your dataflow network, each IEnumerable<FileInfo> generated by the search block is first sent to the move block. If the move block didn't accept it (which never happens here), it would be sent to the operationCancelled block. That doesn't seem to be what you want at all.

After looking at the walkthough you seem to be basing your code on, it does cancellation similar than you, but with one significant difference: it uses LinkTo() with a predicate, which rejects a message that signifies cancellation. If you wanted to do the same, you would need to also use LinkTo() with a predicate. And since I don't think an empty sequence is a good choice to signify cancellation, I think you should switch to null too.

Also, you don't need to use form.Invoke() if you're already using TaskScheduler.FromCurrentSynchronizationContext(), they do basically the same thing.

public ITargetBlock<string> SearchPipeline()
{ 
    var search = new TransformBlock<string, IEnumerable<FileInfo>>(path =>
        {
            try
            {
                return Search(path);
            }
            catch (OperationCanceledException)
            {
                return null;
            }
        });

    var move = new ActionBlock<IEnumerable<FileInfo>>(files =>
        {
            try
            {
                Move(files);
            }
            catch (OperationCanceledException)
            {
                // swallow the exception; we don't want to fault the block
            }
        });

    var operationCancelled = new ActionBlock<object>(_ => form._update(),
        new ExecutionDataflowBlockOptions
        {
            TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
        });

    search.LinkTo(move, files => files != null);

    search.LinkTo(operationCancelled);

    return search;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top