Stuck at: ` Object someObj; await new Task<Object>(() => someObj);`

Weiqi Chen 101 Reputation points
2021-07-29T14:40:21.983+00:00

I'm sorry that I did not explain my intention with more detail demo code at the first place.

Here is more near to my original intention demo code:

I'm am so sorry that I wasted your guys precious time in pervious posted.

using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.VisualStudio.Threading;

namespace ns
{
    using Queue = AsyncQueue<Object>;
    public class Object
    {
        public string Message { get; set; } = string.Empty;
    }

    public class Program
    {
        //This is still a demo code. actually my code is in
        //WPF Desktop App, something like this:
        //  button1.Click += button1_Click;
        //  private async void button1_Click()
        //  {
        //      var queue = new Queue();
        //      await Task.WhenAll(...);
        //  }
        public static async Task Main()
        {
            var queue = new Queue();
            await Task.WhenAll(ProducerAsync(queue), ConsumerAsync(queue));
        }

        static public async Task ProducerAsync(Queue queue)
        {
            int i = 0;
            while (true)
            {
                await Task.Delay(1000);
                queue.Enqueue(new Object() { Message = $"A message with index={i++}." });
            }

        }
        static public async Task ConsumerAsync(Queue queue)
        {

            Object lastObject = null;
            Random rd = new Random();


            EntryPoint:
            //allow some resources, for example TCP connection.
            //

            var timeout = Task.Delay(1000);
            Task<Object> data;

            if (lastObject != null)
            {
                Console.WriteLine("Put pending data into a task for later handling");
                //I Think there is no need to call data.run()(or Task.Run(...))
                //to put the lambda expr into a thread pool run asynchronously
                //since What i want is that just put it into Task and for later 
                //await to receive the object from the task.
                //a task obj should be Scheduling to start when you
                //await it when it not started, is that right?
                data = new Task<Object>(() => lastObject);
                lastObject = null;
            }
            else
            {
                data = queue.DequeueAsync();
            }

            var tasks = new List<Task>() { timeout, data };

            while (tasks.Count > 0)
            {
                var finished = await Task.WhenAny(tasks);
                tasks.Remove(finished);

                if (finished == timeout)
                {
                    try
                    {
                        //Some operations that may throw exceptions,
                        //for example, TCP connection broken.
                        //here is -1, so it won't throw exception for now...
                        //let us focus at data code below.
                        if (rd.Next(0, 3) == -1)
                            throw new Exception("Exception in timeout.");
                    }
                    catch(Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                        if (data.IsCompleted)
                        {
                            lastObject = await data;
                        }
                        goto EntryPoint;
                    }
                    tasks.Add(timeout = Task.Delay(1000));
                }

                if (finished == data)
                {
                    lastObject = await data;

                    try
                    {
                        //Another operations that may throw exceptions
                        //for example, TCP connection broken.
                        if (rd.Next(0, 4) == 0)
                        {
                            throw new Exception("Exception in data.");
                        }
                    }
                    catch(Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                        goto EntryPoint;
                    }

                    Console.WriteLine($"{lastObject.Message} was handled successfully.");

                    //If everything go well.
                    lastObject = null;
                    tasks.Add(data = queue.DequeueAsync());
                }

            }
        }
    }
}

It finally stuck at

A message with index=0. was handled successfully.
A message with index=1. was handled successfully.
A message with index=2. was handled successfully.
A message with index=3. was handled successfully.
Exception in data.
Put pending data into a task for later handling
// Stucked.
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,354 questions
{count} votes

3 additional answers

Sort by: Most helpful
  1. AgaveJoe 26,161 Reputation points
    2021-07-29T15:07:53.01+00:00

    I think you are looking for a pattern like below. Reference doc.

        class Program  
        {  
            static async Task Main(string[] args)  
            {  
                Console.WriteLine("Hello World!");  
                Console.WriteLine("Stuck at \"await task\" ...");  
      
                string str = await ExampleMethodAsync();  
      
                Console.WriteLine("return from await");  
                Console.WriteLine(str);  
            }  
      
            private static async Task<string> ExampleMethodAsync()  
            {  
                await Task.Delay(10);  
                return "Hello World";  
            }  
      
        }  
    
    1 person found this answer helpful.
    0 comments No comments

  2. Karen Payne MVP 35,196 Reputation points
    2021-07-29T14:59:00.81+00:00

    Here is an example working with a method for int and a method for string.

    Full source

    Example 1

    using System;
    using System.Threading.Tasks;
    
    namespace AsyncMain
    {
        class Program
        {
            public static async Task<int> Main(string[] args)
            {
                static Task<string> Simple() => Task.Run(async () =>
                    {
                        await Task.Delay(2000);
                        return $"{nameof(Simple)}";
                    });
    
    
                Console.WriteLine(await Simple());
    
                Console.ReadKey();
                return 0;
            }
    
    
        }
    }
    

    Example 2

    using System;
    using System.Threading.Tasks;
    
    namespace AsyncMain
    {
        class Program
        {
            public static async Task<int> Main(string[] args)
            {
                Console.Title = "async Task<int> Main";
                int number1 = 5, number2 = 10;
                Console.WriteLine($"Sum of {number1} and {number2} is: {await AdditionAsync(number1, number2)}");
    
                Console.WriteLine(await Simple());
    
                Console.WriteLine("Press any key to exist.");
                Console.ReadKey();
                return 0;
            }
            private static Task<int> AdditionAsync(int value1, int value2)
            {
                return Task.Run(() => SumIt(value1, value2));
    
                int SumIt(int x, int y)
                {
                    return x + y;
                }
            }
    
            private static Task<string> Simple() => Task.Run(() => $"{nameof(Simple)}");
        }
    }
    
    0 comments No comments

  3. Weiqi Chen 101 Reputation points
    2021-08-05T01:28:24.477+00:00

    A working demo code below

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Diagnostics;
    using System.Collections.Generic;
    using Microsoft.VisualStudio.Threading;
    
    
    namespace ns
    {
        using Queue = AsyncQueue<Object>;
        public class Object
        {
            public string Message { get; set; } = string.Empty;
        }
    
        public class Program
        {
            //This is still a demo code. actually my code is in
            //WPF Desktop App, something like this:
            //  button1.Click += button1_Click;
            //  private async void button1_Click()
            //  {
            //      var queue = new Queue();
            //      await Task.WhenAll(...);
            //  }
            public static async Task Main()
            {
                var queue = new Queue();
                await Task.WhenAll(ProducerAsync(queue), ConsumerAsync(queue));
            }
    
            static public async Task ProducerAsync(Queue queue)
            {
                int i = 0;
                while (true)
                {
                    await Task.Delay(1000);
                    queue.Enqueue(new Object() { Message = $"A message with index={i++}." });
                }
    
            }
            static public async Task ConsumerAsync(Queue queue)
            {
    
                Object lastObject = null;
                Random rd = new Random();
    
    
                EntryPoint:
                //allow some resources, for example TCP connection.
                //
                var cts = new CancellationTokenSource();
                var timeout = Task.Delay(1000);
                Task<Object> data=null;
    
                if (lastObject != null)
                {
                    //Console.WriteLine("Put pending data into a task for later handling");
                    data = Task.FromResult(lastObject);
                }
                else
                {
                    data = queue.DequeueAsync(cts.Token);
                }
    
                var tasks = new List<Task>() { timeout, data };
    
                while (tasks.Count > 0)
                {
                    var finished = await Task.WhenAny(tasks);
                    tasks.Remove(finished);
    
                    if (finished == timeout)
                    {
                        try
                        {
                            //Some operations that may throw exceptions,
                            //for example, TCP connection broken.
                            //here is -1, so it won't throw exception for now...
                            //let us focus at data code below.
                            if (rd.Next(0, 2) == 0)
                                throw new Exception("Exception in timeout.");
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            cts.Cancel();
                            try
                            {
                                lastObject =  await data;
    
                            }catch when (cts.IsCancellationRequested)
                            {
                                lastObject = null;
                            }
                            goto EntryPoint;
                        }
                        tasks.Add(timeout = Task.Delay(1000));
                    }
    
                    if (finished == data)
                    {
                        var ret = await data;
    
                        try
                        {
                            //Another operations that may throw exceptions
                            //for example, TCP connection broken.
                            if (rd.Next(0, 2) == 0)
                            {
                                throw new Exception("Exception in data.");
                            }
                        }
                        catch (Exception ex)
                        {
                            lastObject = ret;
                            Console.WriteLine(ex.Message);
                            goto EntryPoint;
                        }
    
                        Console.WriteLine($"{ret.Message} was handled successfully.");
    
                        //If everything go well.
                        lastObject = null;
                        tasks.Add(data = queue.DequeueAsync());
                    }
    
                }
            }
        }
    }
    
    0 comments No comments