5

I have this method which I would like to run asynchronously so that I can do other things while it runs. It does not rely on any other Async method (it doesn't call out to another resource, download a file or anything). I would like to avoid using new Task(), Task.Factory.StartTask() and Task.Run(), if possible.

Is it possible to run this method asynchronously, with tidy, readable code and without using Task explicitly?

If not, what is the tidiest way of running the method asynchronously?

Note: Please don't be concerned with the silly logic in the method - I have boiled it down to be deliberately slow but not show my actual code.

public static void main(string[] args)
{
  RunMySlowLogic();
}

private void RunMySlowLogic()
{
  while (true)
    for (int i=0; i<100000000;i++)
      if (i == new Random().Next(999))
        return true;
}

Currently, I believe that I would need to wrap the method in a lambda or Task and mark it async. Where would the await go?

i3arnon
  • 113,022
  • 33
  • 324
  • 344
Matt W
  • 11,753
  • 25
  • 118
  • 215
  • 1
    see this post http://stackoverflow.com/questions/32617702/how-to-async-this-long-running-method – Sievajet Sep 16 '15 at 20:07
  • 2
    Console programs can't `await`. – Scott Chamberlain Sep 16 '15 at 20:07
  • If you just want to run this code in a separate thread, and it does not need to wait on any other async methods, then you can just do `Task.Factory.StartNew(RunMySlowLogic)`. You can add the `LongRunning` flag if you like as well. – odyss-jii Sep 16 '15 at 20:07
  • 3
    *If not, what is the tidiest way of running the method asynchronously?* Your method does nothing async. You want to run code in parallel. Why don't you want to use `Task.Run`? – Yuval Itzchakov Sep 16 '15 at 20:09
  • 1
    sievajet You linked to my post. – Matt W Sep 16 '15 at 20:10
  • http://stackoverflow.com/questions/9208921/async-on-main-method-of-console-app – MethodMan Sep 16 '15 at 20:10
  • scott chamberlain I know main() methods can't be awaited, but I am not calling it from there. – Matt W Sep 16 '15 at 20:10
  • odyss-jii Is it possible to avoid StartNew()? I would like to use nothing but async and await keywords, but is that possible or am I forced to create a Task object somewhere in my method? – Matt W Sep 16 '15 at 20:10
  • Yuval - I know, this is just an example. My real code is more complex, but too long and proprietary to post here. I would like to know the cleanest way of async'ing that method, without using Task, if possible. – Matt W Sep 16 '15 at 20:12
  • Matt - Using `async-await` will not help here, your method isn't asynchronous. We cant help you *asyncify* this code since this example makes no sense at all. – Yuval Itzchakov Sep 16 '15 at 20:12
  • Yuval - But it can be run on another thread. Call it the background, if you like, but that's what I'm aiming at. – Matt W Sep 16 '15 at 20:13
  • @MattW You do that with `Task.Run`. – i3arnon Sep 16 '15 at 20:13
  • @i3arnon - What is the cleanest way of doing that? – Matt W Sep 16 '15 at 20:14
  • @MattW as I posted in my answer: `Task.Run(() => RunMySlowLogic());` – i3arnon Sep 16 '15 at 20:14
  • Matt - I think you might have a miss-understanding of what `Task.Run` does. You want to avoid it for some reason, but that's exactly what you need. – Yuval Itzchakov Sep 16 '15 at 20:15

2 Answers2

11

You're confusing two different things. You can run this in the background, and this method can be asynchronous. These are 2 different things and your method can do either, or both.

If you do something asynchronous in that method, like Task.Delay or some non-blocking I/O then call that method, await the returned task and make the method itself async:

async Task RunMySlowLogicAsync()
{
    while (true)
    {
        // ...
        await Task.Delay(1000);
    }
}

If you don't have such a thing then your method isn't asynchronous, it's synchronous. You can still run it in the background on a different (ThreadPool) thread while you do other things using Task.Run:

var task = Task.Run(() => RunMySlowLogic());
i3arnon
  • 113,022
  • 33
  • 324
  • 344
0

There are multiple ways of executing code asynchronously in the .NET environment. Have a look at the Asynchronous Programming Patterns MSDN article.

Tasks are to make your job easier. I think the only valid reason to avoid using tasks is when you are targeting an older version of .NET.

So without Tasks, you can start a thread yourself, or use a ThreadPool (Tasks do this internally).

public static void main(string[] args)
{
  var are = new AutoResetEvent(false);
  ThreadPool.QueueUserWorkItem(RunMySlowLogicWrapped, are);
  // Do some other work here
  are.WaitOne();
}

// you have to match the signature of WaitCallback delegate, we can use it to communicate cross-thread
private void RunMySlowLogicWrapped(Object state) {
  AutoResetEvent are = (AutoResetEvent) state;
  RunMySlowLogic();
  are.Set();
}

private bool RunMySlowLogic() 
{
  while (true)
    for (int i=0; i<100000000;i++)
      if (i == new Random().Next(999))
        return true;
}
Tamas Hegedus
  • 28,755
  • 12
  • 63
  • 97