Simone
Simone

Reputation: 2430

Run two task asynchronously

I'm running a synchronous method. Inside it I have to run two big method, so I was thinking to run them asynchronously.. I was thinking something like

public void MyFunc()
{
    var doWorkTask_1 = DoWork1();
    var doWorkTask_2 = DoWork2();

    var result1 = await doWorkTask_1;
    var result2 = await doWorkTask_2;

    if(result1 == result2) 
       ....

    Thread.Sleep(syncInterval);
}

To do this i need that:

  1. DoWork1 and DoWork2 are asynchronous;
  2. MyFunc is asynchrous too;

But no method is asynchronous!!!

SO I tried to do in another way:

public void MyFunc()
{
    var doWorkTask_1 = Task.Run(() => DoWork1());
    var doWorkTask_2 = Task.Run(() => DoWork2());

    var result1 = doWorkTask_1.Result;
    var result2 = doWorkTask_2.Result;

    if(result1 == result2) 
       ....

    Thread.Sleep(syncInterval);
}

So, 1st question: Do I have written same thing in two different ways?

2nd question. I have to run the MyFunc method every X time, so I call it in this way:

Task.Factory.StartNew(MyFunc);

Can I call it simply

MyFunc();

My question is because inside myFunc I have a Thread.Sleep. Can I let sleep the main thread or is better to let sleep a thread inside the main?

I hope I have been clear. Thank you.

Upvotes: 3

Views: 1488

Answers (3)

i3arnon
i3arnon

Reputation: 116548

If you can't do async all the way, and by asynchronous you mean that you want to process DoWork1 and DoWork2 concurrently on different threads then you can use Task.Run to offload the work to a different thread and Task.WaitAll to wait synchronously for both tasks to complete:

public void MyFunc()
{
    var task1 = Task.Run(() => DoWork1());
    var task2 = Task.Run(() => DoWork2());

    Task.WaitAll(task1, task2);
    if (task1.Result == task2.Result)
    {
        // ...
    }

    Thread.Sleep(syncInterval);
}

Now, since this uses 3 threads (two ThreadPool threads in Task.Run and the calling thread blocked on Task.WaitAll) when we only need 2 we can simplify and optimize the example by executing one of the operations on the calling thread:

public void MyFunc()
{
    var task1 = Task.Run(() => DoWork1());
    var result2 = DoWork2();

    if (task1.Result == result2)
    {
        // ...
    }

    Thread.Sleep(syncInterval);
}

Upvotes: 1

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

Have I written same thing in two different ways?

No. Your first method will execute two units of work in parallel, and will asynchronously wait on the first one, then the second one.

Your second method will execute two units of work in parallel, and will synchronously wait on the first one, then on the second one.

Can I let sleep the main thread or is better to let sleep a thread inside the main?

That depends on what your application is doing. You could turn MyFunc to be async so you can use Task.Delay instead, which internally uses a timer and doesn't block (and you may also pass it a CancellationToken if needed):

public async Task MyFuncAsync()
{
   // Do work

   await Task.Delay(syncInterval);
}

Side note:

It seems to me like you may be using async over sync, which in general is a questionable approach. I would advise against it.

Instead, like in your first example, explicitly invoke Task.Run on these workers:

public async Task MyFuncAsync()
{
    var firstTask = Task.Run(() => DoWork1());
    var secondTask = Task.Run(() => DoWork2());

    await Task.WhenAll(new[] { firstTask, secondTask });
    await Task.Delay(syncInterval);
}

Upvotes: 6

Gusdor
Gusdor

Reputation: 14334

Use Task.WhenAll to create a new task, encapsulating both your worker tasks.

Creates a task that will complete when all of the supplied tasks have completed.

https://msdn.microsoft.com/en-us/library/hh194874%28v=vs.110%29.aspx

public async void MyFunc()
{
    var doWorkTask_1 = DoWork1();
    var doWorkTask_2 = DoWork2();

    var results = await Task.WhenAll(doWorkTask_1, doWorkTask_2);
}

Upvotes: 2

Related Questions