0

I have a console application with have two threads as:

    public static async void Thread1()
        {
            for (int i = 0; i < 100; i++)
            {
                Debug.WriteLine("Thread1 " + i);
                await MyFunc();
            }
        }

    public static async void Thread2()
        {
            for (int i = 0; i < 100; i++)
            {
                Debug.WriteLine("Thread2 " + i);
                await MyFunc();
            }
        }
    public static void Main(string[] args)
        {
            MainAsync(args).GetAwaiter().GetResult();
        }
    private static async Task MainAsync(string[] args)
        {

            Console.WriteLine("Before start thread");

            Thread tid1 = new Thread(Thread1);
            Thread tid2 = new Thread(Thread2);

            tid1.Start();

            tid2.Start();
        }

    public static async Task MyFunc()
        {
         //do something
        }

However, when the application run and terminates, it seems that only each thread is run just once as I see only below things in output:

 Before start thread
    Thread1 0
    Thread2 0
//some thing from MyFunc

I expect or rather wannt to run each thread till the for loop.It seems to me that the for loop continues to run despite the await. If yes, what could be other probable approach.

Any leads would be helpful.

learntogrow-growtolearn
  • 1,190
  • 5
  • 13
  • 37
  • Why new Thread() vs await Thread1()? Or adding thread1() and THread2() to an array and using Task.WaitAll()? – Shane Ray Mar 08 '18 at 01:51
  • I copied your code and I see `Thread1 0 - Thread1 99` and `Thread2 0 - Thread2 99` in the Debug Output window... so no repro for me. – Rufus L Mar 08 '18 at 01:54
  • Indeed. Both comments above are highly relevant. What does `MyFunc` actually do? – spender Mar 08 '18 at 01:57
  • 1
    The interchangeablity between `Thread` and `Task` that you are presenting makes me worry that you don't really understand the difference. ["There is no thread"](https://blog.stephencleary.com/2013/11/there-is-no-thread.html) – spender Mar 08 '18 at 01:59

3 Answers3

2

You seem to have a lot of confusion about the role of threads and tasks, so it's a good idea to read up about it. Steven Cleary has a nice write-up about this. "There Is No Thread"

From the comments, it seems that your actual intention here is to run two async tasks in parallel, then to wait until they are both finished.

If you want to wait for two async tasks to complete in parallel, make sure your async methods actually return Task then:

Task task1 = DoSomethingAsync(); //don't await
Task task2 = DoSomethingElseAsync(); //don't await

then you can wait asynchronously for Task.WhenAll:

await Task.WhenAll(task1,task2);

You really don't need to be involving Thread at all.

spender
  • 117,338
  • 33
  • 229
  • 351
2

You aren't doing anything to wait for the threads. The main routine will just continue on until it returns to the O/S, which will kill the process and any child threads. Since you aren't doing anything else, this happens almost immediately, cutting both threads' lives short.

If you want to wait for the threads to finish, you can refer to this answer and write some variation of

while (thread1.IsAlive || thread2.IsAlive)
{
    //Do something to wait
}

...before exiting.

That being said, you should probably using Tasks instead of threads, e.g.

public static async Task Task1()
{
    for (int i = 0; i < 100; i++)
    {
        Debug.WriteLine("Task1 " + i);
        await MyFunc();
    }
}

public static async Task Task2()
{
    for (int i = 0; i < 100; i++)
    {
        Debug.WriteLine("Task2 " + i);
        await MyFunc();
    }
}

And then to execute and wait for both of them:

Task.WaitAll
( 
    new[] 
    {
        Task1(), 
        Task2() 
    } 
);

See this code in action on DotNetFiddle

See also What is the difference between tasks and threads?

John Wu
  • 50,556
  • 8
  • 44
  • 80
1

Use async Task instead of async void

private static async Task MainAsync(string[] args)
{
    Console.WriteLine("Before start thread");
    var task1 = Thread1();
    var task2 = Thread2();
    var taskList = new [] { task1, task2 };
    Task.WaitAll(taskList);
}
spender
  • 117,338
  • 33
  • 229
  • 351
Shane Ray
  • 1,449
  • 1
  • 13
  • 18
  • Does your solution give different results than the original? I was unable to repro his original problem. Both your code an his produce the same results for me. – Rufus L Mar 08 '18 at 02:00
  • @RufusL Until we see what `MyFunc` is actually doing, we're in the cold. – spender Mar 08 '18 at 02:01
  • The original code has a race condition. The application can finish before the work on the thread. – Shane Ray Mar 08 '18 at 02:01
  • @spender MyFunc has another await to set the same object in the Redis Cache. – learntogrow-growtolearn Mar 08 '18 at 02:02
  • @ShaneRay What awaits each thread does is executing MyFunc 100 times for the first thread and then running it for the Thread2. I want them to run in parallel so that I see, for example, "Thread1 23, Thread2 15" in output. – learntogrow-growtolearn Mar 08 '18 at 02:04
  • @ShaneRay That's quite insightful and explains why an empty `MyFunc` implementation might lead to different results to those being observed. You should explain this in your answer rather than in the comments. – spender Mar 08 '18 at 02:04
  • @learntogrow-growtolearn updated comment yo run the two tasks in parallel.. did on mobile.. syntax may be a little off – Shane Ray Mar 08 '18 at 02:09
  • @ShaneRay Please take a moment to read this. It will help you a lot: https://stackoverflow.com/help/formatting – spender Mar 08 '18 at 02:18
  • @spender thanks just having trouble with the mobile editor – Shane Ray Mar 08 '18 at 02:19