Q: Continue with a method after completing producer-consumer I have a producer-consumer application in WPF. After I click a button.
private async void Start_Click(object sender, RoutedEventArgs e)
{
     try
     {
        // set up data
        var producer = Producer();
        var consumer = Consumer();
        await Task.WhenAll(producer, consumer);
        // need log the results in Summary method 
        Summary();
     }
}

The summary method is a void one; I assume it is proper.
private void Summary(){}
async Task Producer(){ await something }
async Task Consumer(){ await something }

EDIT:
My question is in Summary() method I have to use the calculated values from the tasks, however the Consumer task is a long running process. The program run Summary quickly even not getting the updated values. It use the initial values.
My thought:
await Task.WhenAll(producer, consumer);
Summary(); 

EDIT2: 11:08 AM 11/05/2014
private void Summary()
{
     myFail = 100 - mySuccess;
     _dataContext.MyFail = myFail; // update window upon property changed

 async Task Consumer()
 {
     try
     {
         Dictionary<string, string> dict = new Dictionary<string, string>();
         var executionDataflowBlockOptions = new ExecutionDataflowBlockOptions
         {
                MaxDegreeOfParallelism = 5,
                CancellationToken = cToken
         };
         var c = new ActionBlock<T>(
          t=>
         {
              if (cToken.IsCancellationRequested)
                  return;
               dict = Do(t, cToken);
               if(dict["Success"] == "Success")
                   mySuccess++;

The current problem is mySuccess is always the initial value in Summary method.

A: You can use ContinueWith method to execute Summary after both producer and consumer have finished:
Task.WhenAll(producer, consumer)
    .ContinueWith(continuation => Summary());

EDIT 1
It seems that you are abusing or using wrong the Producer/Consumer pattern.
The producer is supposed to produce the values and shovel them into one end of a communication pipe. On the other end of the pipe, the consumer consumes the values as they become available. In other words, the consumer waits for the producer to produce some value and to put the value in the pipe and for the value to arrive at the end of the pipe.
Usually this involves some sort of signaling mechanism where the producer signals (awakes) the consumer whenever a value has been created.
In your case, you don't have the signaling mechanism and I strongly suspect that your producer is generating only one value. If the later is the case you can just return a value from the "producer".
If however, your producer is creating more than one values, you can use the BlockingCollection<T> class to send values from producer to consumer.
In your Producer class, get a reference to the pipe and put data into it:
public class Producer
{
    private BlockingCollection<Data> _pipe;

    public void Start()
    {
        while(!done)
        {
            var value = ProduceValue();
            _pipe.Add(value);
        }
        // Signal the consumer that we're finished
        _pipe.CompleteAdding();
    }
}

In the Consumer class wait for the values to arrive and process each one:
public class Consumer
{
    private BlockingCollection<Data> _pipe;

    public void Start()
    {
        foreach(var value in _pipe.GetConsumingEnumerable())
        {
            // GetConsumingEnumerable will block until a value arrives and 
            // will exit when producer calls CompleteAdding()
            Process(value);
        }
    }
}

Having the above in place you can use ContinueWith or await on the WhenAll method to run the Summary.
EDIT 2
As promised in the comments I have analyzed the code you've posted on MSDN Forum. There are several problems in the code.
First of all and the simplest one to fix is that you're not incrementing the counter in a thread-safe manner. An increment (value++) is not an atomic operation so you should be careful when incrementing shared fields. An easy way to do this is:
Interlocked.Increment(ref evenNumber);

Now, the actual problems in your code:


*

*As I mentioned earlier, the consumer does not know when the producer has finished producing the values. So, after the producer exits the for block it should signal that it has finished. The consumer waits for the finish signal of the producer; otherwise it will wait forever for the next value but there won't be one.

*You are linking the BufferBlock with the consumer code which starts to execute but you're not waiting for the consumer block to finish - you're only waiting 0.5 of a second and exit the consumer method leaving the worker threads of the consumer block to do their work in vain.

*As a consequence of the above, your Report method executes before the processing is finished outputting the value of the evenNumber counter at the moment when the method executes not when all processing is finished.
Below is the edited code with some comments:
class Program
{
    public static BufferBlock<int> m_Queue = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1000 });
    private static int evenNumber;

    static void Main(string[] args)
    {
        var producer = Producer();
        var consumer = Consumer();

        Task.WhenAll(producer, consumer).Wait();
        Report();
    }

    static void Report()
    {
        Console.WriteLine("There are {0} even numbers", evenNumber);
        Console.Read();
    }

    static async Task Producer()
    {
        for (int i = 0; i < 500; i++)
        {
            // Send a value to the consumer and wait for the value to be processed
            await m_Queue.SendAsync(i);
        }
        // Signal the consumer that there will be no more values
        m_Queue.Complete();
    }

    static async Task Consumer()
    {
        var executionDataflowBlockOptions = new ExecutionDataflowBlockOptions
        {
            MaxDegreeOfParallelism = 4
        };
        var consumerBlock = new ActionBlock<int>(x =>
        {
            int j = DoWork(x);
            if (j % 2 == 0) 
                // Increment the counter in a thread-safe way
                Interlocked.Increment(ref evenNumber);
        }, executionDataflowBlockOptions);

        // Link the buffer to the consumer
        using (m_Queue.LinkTo(consumerBlock, new DataflowLinkOptions { PropagateCompletion = true }))
        {
            // Wait for the consumer to finish.
            // This method will exit after all the data from the buffer was processed.
            await consumerBlock.Completion;
        }
    }

    static int DoWork(int x)
    {
        Thread.Sleep(100);
        return x;
    }
}

