locked
How to use async-await pattern with background task RRS feed

  • Question

  • Hi, I'm new to async-await pattern and I'd like to get deeper understanding of asynchronous operations in 4.5 Fw. I have created small peace of code to simulate long-running asynchronous method.

            static async Task DoSomethingAsync()
            {
                LogOperation("Doing something...");
                Thread.Sleep(500);
    
                LogOperation("Waiting something...");
                await Task.Delay(500);
    
                LogOperation("Doing something again...");
                Thread.Sleep(500);
            }
    
            static void LogOperation(string operationName)
            {
                Console.WriteLine("[" + Thread.CurrentThread.ManagedThreadId + "] " + operationName);
            }

    The goal is to execute DoSomethingAsync() in background thread without blocking main (UI) thread and do not block any thread on waiting operation (numer 2).  So it would be truly asynchronous. I have added printing of thread id on each separate operation, so I can understand which thread is used to execute each step of async method. 

    Try number 1:

                LogOperation("Start async methods.");
                Task.WaitAll(DoSomethingAsync(), DoSomethingAsync());
                LogOperation("Done.");

    Results:
    [10] Start async methods.
    [10] Doing something...
    [10] Waiting something...
    [10] Doing something...
    [10] Waiting something...
    [6] Doing something again...
    [12] Doing something again...
    [10] Done.

    It's not what I wanted, because most of code was executed on main thread.

    Try 2:

                LogOperation("Start async tasks.");
                Task.WaitAll(
                    Task.Factory.StartNew(() => DoSomethingAsync()),
                    Task.Factory.StartNew(() => DoSomethingAsync()));
                LogOperation("Done.");
    

    Results:

    [10] Start async tasks.
    [6] Doing something...
    [12] Doing something...
    [6] Waiting something...
    [12] Waiting something...
    [10] Done.
    [6] Doing something again...
    [14] Doing something again...

    That is better, but seems async method is not attached to tasks I have launched via Task.Factory. So I can't wait for them, get result or catch exception (if any).

    Any clues?

     
    Thursday, October 11, 2012 1:13 PM

All replies

  • Instead of using Task.WaitAll, use "await" in your main thread calls as followed:

    LogOperation("Start async tasks."); await DoSomethingAsync();

                await DoSomethingAsync();

    LogOperation("Done.");

    HTH

    Sameer


    If this answers your question, please Mark it as Answer. If this post is helpful, please vote as helpful.

    Thursday, October 11, 2012 2:14 PM
  • Error 1 'AsyncMethodsTest.Program.Main(string[])': an entry point cannot be marked with the 'async' modifier
    Thursday, October 11, 2012 2:19 PM
  • I don't like using threads because it is difficult to commincate between the main thread and the tasks.  Instea I like using classes as threads.  An aynchronous class runs exactly the same as a task but you have better communications and synchronization between the main thread and the tasks

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Timers;
    namespace ConsoleApplication1
    {
        class Program
        {
            class state
            {
                public int number;
            }
            static state mystate = new state();
            static void Main(string[] args)
            {
                mythread thread = new mythread();
                thread.runtask(1);
            }
            class mythread
            {
                public void runtask(int state)
                {
                    Timer mytimer = new Timer();
                    mytimer.Interval = (double)5;
                    mytimer.Start();
                    
                }
            }
        }
    }


    jdweng

    Thursday, October 11, 2012 2:33 PM
  • I have found a trick which allows to achieve my goal.

            static Task WrappTask(Func<Task> taskFunc)
            {
                return Task.Factory.StartNew(() => taskFunc().ContinueWith(t => t.Wait(), TaskContinuationOptions.AttachedToParent));
            }
    
            static void Main(string[] args)
            {
                LogOperation("Start async tasks.");
                Task.WaitAll(WrappTask(DoSomethingAsync), WrappTask(DoSomethingAsync));
                LogOperation("Done");
            }
    [10] Start async tasks.
    [6] Doing something...
    [11] Doing something...
    [6] Waiting something...
    [11] Waiting something...
    [11] Doing something again...
    [6] Doing something again...
    [10] Done

    But this looks like an ugly hack. There must be better solution how to do this.


    Thursday, October 11, 2012 2:34 PM
  • async/Await is actually much smarter than you're giving it credit for.  Marking a method doesn't just make it run in a background thread; it's much, much more powerful than that.

    When you have an async method essentially all of it will run in the UI thread.  Your two `Thread.Sleep` calls are running in the UI thread.  It's the await that *isn't* (potentially) running in the UI thread.  Your Sleeps are blocking the UI thread, but the Task.Delay actually *isn't* blocking the UI thread.

    If you have a long running task you will need to use `Task.Run` to explicitly run that task in a background thread.  You can then `await` on the Task that is returned so that, rather than putting all of the code you would like to run (that alters the UI) in a continuation, you can just run it in the method you were in before.

    Here's a better example:

    private async void button1_Click(object sender, EventArgs e)
    {
        label1.Text = "Starting First Task";
        await Task.Run(() =>LongRunningTask());
    
        label1.Text = "Waiting for a bit";
        await Task.Delay(1000);
    
        label1.Text = "Doing Second Task";
        await Task.Run(() => LongRunningTask());
    
        label1.Text = "All Done";
    }
    
    private void LongRunningTask()
    {
        Thread.Sleep(2000);
    }

    Here the *advantage* of using this model is that most of the code is running in the UI thread which is why I intentionally changed the log methods to UI changes.  It demonstrates updating the UI after each of the long running tasks.  Normally that would be done via continuations which is much messier.

    Thursday, October 11, 2012 2:40 PM
  • Sameer, your code wouldn't solve the problem...
    Thursday, October 11, 2012 2:41 PM
  • Error 1 'AsyncMethodsTest.Program.Main(string[])': an entry point cannot be marked with the 'async' modifier
    It's worth noting that async/await makes less sense in console apps.  You can do it, sure, but there are many less situations in which you would want to because you don't have a message loop, nor do you have tasks that need to take place in a main thread.  If you just want a simple way to run some code in a background thread just use `Task.Run`.  That hasn't changed.
    Thursday, October 11, 2012 2:43 PM
  • Servy42, thanks for you reply. But I'd like to achieve something slightly different that your example demonstrate. In your example async method is executed on main thread. Id' like to have async method fully executed on background thread and never returns back to UI thread until all done. In other words, I'd like to use async method inside background task instead of using background tasks inside async method. 
    Thursday, October 11, 2012 2:56 PM
  • Servy42, thanks for you reply. But I'd like to achieve something slightly different that your example demonstrate.

    From what I can tell it's doing what your code intends to do, and this is how async/await was designed to be used.

    In your example async method is executed on main thread.

    Yes, that will pretty much always be the case. It doesn't make sense to use an async method any other way really.

    I'd like to have async method fully executed on background thread and never returns back to UI thread until all done.

    I think this is a termanology issue here (one that the C# team specifically expected to be a problem from the start). When a method is `async` it doesn't mean that it run asynchronously, it just means that, somewhere inside of it, there is a task that runs asynchronously. It will start out running synchronously, it will, at some point, hit one or more asynchronous tasks (marked with `await`). When it reaches those it will wire up the remainder of the method as a continuation of that asynchronous task and then return immediately. The Task it returns will be complete when the method reaches it's end.

    In other words, I'd like to use async method inside background task instead of using background tasks inside async method. 

    Why? What would that give you? This is substantially *less* useful. It's actually a rather substantially different way of appraoching these problems. You're thinking of it using the 4.0 mindset. This is a completely different shift in the way of approaching the problem. (Even though, behind the scenes, it will result in code that's actually very similar; the compiler just does the work for you.)

    As I said, it really doesn't make much sense to use async/await in a console app.  There are situations, sure, but you need to work rather hard at it to come up with them.

    If the idea is simply to run some code in the UI thread, run some code all in a background thread, and then run some more code in the UI thread, that's exactly what my method does, it just shifts back and forth several times.  Each of the label setting are done in the UI thread, and all of the long running tasks are executed in backround threads.  If you wanted, you could remove all of the label sets other than the first and last and have everything in the middle running in background threads (although possibly not the *same* background thread).

    I would suggest actually running the method I provided in a winforms app.  You'll see that none of the long running tasks (nor the task.dealy) actually block the UI.  They are run in the background, but despite that all of the label updates will run in the UI thread, work properly, and happen instantaneously.  It seems a bit backwards, but it's really not.  It's actually the way most people try to write their programs *before* they learn how asynchronous coding has traditionally been done.  You've gotten so used to doing it "backwards" that doing it "forwards" again seems wrong to you.  It'll just take some getting used to.
    • Edited by servy42 Thursday, October 11, 2012 3:17 PM
    Thursday, October 11, 2012 3:13 PM
  • Servy42, thanks for you reply again.  I'm developing server-side applications such as stand-alone services. So in most cases i even don't have main or UI thread at all. My goal of using async-await pattern is to achieve good scalability and performance by reusing threads and avoiding frequent context switching. Moreover, each thread eats a lot of memory, and having hundreds of them (as I usually have) is huge overkill. 
    Thursday, October 11, 2012 3:31 PM
  • So the key there is simply to use a thread pool rather than using explicit threads.  If you create tasks using (for example) Task.Run or Task.Factory.StartNew it will generally be creating tasks in the thread pool.  It will automatically handle the creation of some number of actual threads, and of scheduling those tasks to run on the actual threads.

    You appear to have no use of the async/await model, from what you've described.

    Thursday, October 11, 2012 3:59 PM
  • My services usually do complex tasks. They may call other services, load something from disk or DB, or do another blocking/waiting operations. It doesn't matter if I use my own threads or thread pool. If I block thread from the pool, it forces pool to create a new thread. So using thread pool does not  reduce number of threads. And async-await pattern looks like a solution in this case.
    Friday, October 12, 2012 10:46 AM
  • My services usually do complex tasks. They may call other services, load something from disk or DB, or do another blocking/waiting operations.
    This is exactly what I meant when I asked if your tasks would be doing mostly IO, as it will prevent you from being able to effectively cancel them unless those IO tasks were specifically designed to support cancellation (most aren't).
    It doesn't matter if I use my own threads or thread pool. If I block thread from the pool, it forces pool to create a new thread.
    No, it doesn't. That's a false assumption.
    So using thread pool does not  reduce number of threads.
    That is incorrect, due to your false assumption.
    And async-await pattern looks like a solution in this case.
    No, it's really not. All you really need here is to be creating `Task` objects, and letting them run in the thread pool. Using Async/Await (in your particular case) wouldn't even avoid doing that. You don't have a synchronization context, so in order to create the additional tasks to await them you'll realistically need to start new ones (that run in the thread pool) and without a synchronization context you won't have one to marshal back to, so the continuations won't run in the "main thread" (because it's a console application) they will just be another task scheduled to run in the thread pool.
    Friday, October 12, 2012 3:06 PM
  • Servy42, please run this simple code for awhile to see my 'false' assumption.

                ManualResetEvent objToWait = new ManualResetEvent(false);
    
                for (int i = 0; i < 500; i++)
                    Task.Factory.StartNew(() => objToWait.WaitOne());
    
                while (!Console.KeyAvailable)
                {
                    Console.WriteLine(System.Diagnostics.Process.GetCurrentProcess().Threads.Count);
                    Thread.Sleep(1000);
                }
    
                objToWait.Set();

    While a thread is blocked by any synchronization primitive (lock, wait handle, semaphore etc) it can't be used to execute any other code. It just waits till the lock (handle) is released. So the framework (ThreadPool) have to create new threads in order to execute other tasks in the queue.

    Now compare this with async-await pattern and feel the difference:

                TaskCompletionSource<object> objToWait = new TaskCompletionSource<object>();
    
                for (int i = 0; i < 500; i++)
                    Task.Factory.StartNew(async () => await objToWait.Task);
    
                while (!Console.KeyAvailable)
                {
                    Console.WriteLine(System.Diagnostics.Process.GetCurrentProcess().Threads.Count);
                    Thread.Sleep(1000);
                }
    
                objToWait.SetResult(null);


    Friday, October 12, 2012 8:38 PM
  • While a thread is blocked by any synchronization primitive (lock, wait handle, semaphore etc) it can't be used to execute any other code. It just waits till the lock (handle) is released.

    So far so good

    So the framework (ThreadPool) have to create new threads in order to execute other tasks in the queue.

    Nope; this is where your logic breaks down. Instead of creating new threads it can just wait. It doesn't need to create a new thread *every time a thread pool thread waits*. You can have, for example, 4 thread pool threads to start with, go add 16 tasks (each of which just wait for a while) and have those 4 threads plow through the 16 tasks without creating any more threads. It will work on 4 tasks, sitting there waiting for them to finish. When they finish 4 more will start, and so on, until the queue is emptied. Now, if the threadpool notices that there are a lot of items in the queue for an extended period of time it may create more threads to help do the work quicker, and if it notices lots of idle threads it may let them end so that their resources can be freed.

    As for the code snippets, they simply aren't equivalent.  In your first example you're actually putting the thread pool thread to sleep, and you're not letting it wake up for a long time.  Because the thread pool is noticing lots of threads asleep for long periods of time it's constantly creating new threads (which isn't wrong).  If you were actually doing real IO work there that's likely what you'd be seeing (note that in your specific case you'll almost never have more than one or two tasks in the queue by the time you add the next one, so it's a non-issue).  Your particular code snippet here also is more or less designed to be mean to the thread pool.  You start a whole mess of tasks, make all of them wait for a while, and then release them all.  There is no opportunity here to "re-use" threads, and that's what makes thread pools useful.  

    If, instead, you wrote a sample that more closely modeled what your  *real* application will do then you'll get a better idea of what's going on.  What you should be doing is adding tasks that take a few seconds to run (maybe choose a random number of seconds between 1 and 5) and add a new one of those tasks every 2 seconds over a period of several minutes.  What you'll see is that as each task finishes the thread that was running it will be able to be re-used to run the next available task.  If you tweak the numbers such that the average sleep rate is less than the creation rate you will only need 1 thread pool thread.  (That's not true of the numbers I gave, so you'll likely see it go from 1 to 2 at some point).  This means that you'll have 1 (maybe two or three) threads used to process several dozen tasks, even though each one of those tasks was waiting for a while.  The key point here is that the thread pool only needs to have enough threads to handle the number of *concurrent* wait operations.

    So, now that we've analyzed the first code snippet, it's time do delve into the second.  So the key here is that there isn't any actual waiting operations.  `await` makes it *appear* as if the method is waiting/blocking, but it's not.  It's an illusion (and a very cool one at that).  

    Your code starts out creating a new task via StartNew, meaning it's a task that will be processed by the thread pool.  It's running an async method.  The first thing that the method does is call `await`.  This means that it will evaluate the expression to it's right to a Task (which is simple enough, as the task already exists from the TCS).  It will then take that task and add a continuation to it; that continuation will contain the remainder of the async method.  (There is nothing after the `await` call, so that continuation will be a no-op.)  Once the continuation is added the async method will return (either void or the `Task` that represents the return value of the continuation).

    Because the async method actually returns *right away* it's not doing any blocking of thread pool threads, so it only needs one thread to process all of those tasks (all their doing is attaching a continuation; that doesn't take long).

    For your async/await method to actually represent what you're doing the `Task` objects that you `await` on need to be tasks that represent some actual IO work that is happening.

    Now, as I've said, async/await is really, really cool, and it can make a lot of complex or boilerplate code much simpler.  This simply isn't quite the right place to use it.
    • Edited by servy42 Friday, October 12, 2012 9:30 PM
    Friday, October 12, 2012 9:16 PM
  • Servy42, Let's imagine we have WCF service which process requests in following way:

      • Receive and validate request
      • Call another WCF service for some data (let's call it Service2)
      • Process data returned by Service2
      • Return results

    Let's assume Service2 processes each request 2 seconds in average and it is very scalable (server farm) so it can process any number of requests in parallel. In addition, let's assume all other operations are relatively quick, so we may not take them into account.

    So if you have 4 threads and and your implementation utilizes blocking WCF calls, you can process 2 request per second. It's not very good performance. You are limited by 4 threads and 2 seconds on each request.

    Contrariwise, if you use async-await pattern in this case (call Service2 asynchronously), you can process 1000 requests per second or more (it's depends on your hardware) and have the same 4 threads.

    I can write and send a small demonstration project, if you don't believe me :)

    Monday, October 15, 2012 2:00 PM
  • Servy42, Let's imagine we have WCF service which process requests in following way:

      • Receive and validate request
      • Call another WCF service for some data (let's call it Service2)
      • Process data returned by Service2
      • Return results

    Let's assume Service2 processes each request 2 seconds in average and it is very scalable (server farm) so it can process any number of requests in parallel. In addition, let's assume all other operations are relatively quick, so we may not take them into account.

    So if you have 4 threads and and your implementation utilizes blocking WCF calls, you can process 2 request per second. It's not very good performance. You are limited by 4 threads and 2 seconds on each request.

    Contrariwise, if you use async-await pattern in this case (call Service2 asynchronously), you can process 1000 requests per second or more (it's depends on your hardware) and have the same 4 threads.

    I can write and send a small demonstration project, if you don't believe me :)

    async/await doesn't actually require more than a single thread to work.  It is actually fairly common to use async/await without generating *any* asynchronous tasks.  Now, you can use async/await with asynchronous tasks, and it can work effectively with them in the proper context, but they are still separate contexts.

    Now, I haven't done much WCF in general, and none as of .NET 4.5, but I'm unsure if the server side WCF handlers are designed to work with async/await.  They would need to be designed to accept async handlers, something I doubt the older versions support (I don't know if they added support for it in the new version or not).

    Remember that you're asking this entire question because you're not particularly familiar with async/await, and you don't seem to really understand what async/await operations actually compile into.  I'm trying to explain what it does and how it works, and you're now trying to say that you do know what it does and how it will solve your particular problem.  If you knew how it worked and how it could solve your problem than why ask the question in the first place?

    In any case, you seem to think that I'm telling you to never use async await or that it is in some way not useful.  That's simply not true.  It is an amazing feature that, in the proper context, will greatly simplify code that is frequently troublesome for new programmers and is time consuming (as a result of requiring lots of boilerplate code) for more experienced programmers.  Having said all of that, async/await won't be utilized in all asynchronous programming models.  In the end all it is doing is creating continuations of `Task`s.  While many asynchronous programming models involve a lot of continuations, not all do.  Additionally, many IO or other long running tasks can benefit from being made asynchronous and using continuations, but again, not all *can*.  If you're simply looking for a useful application of async/await, look no further than my first reply to your thread.  If you're looking for more, I can certainly oblige with other examples.  If you're simply looking to solve this particular problem that you have, then you should be asking yourself (and others if you need to ask for help) how to solve that problem in whatever way is best, rather than how to use async/await to solve that problem.

    Monday, October 15, 2012 2:32 PM
  • Servy42, I do know how async/wait works and I do know it is very useful in my case. The only question I asked is how to properly call async method in a background task. You have no answer for my question.  But thank you for your effort.

    Monday, October 15, 2012 4:18 PM
  • How about this

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Timers;
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                List<runtask> tasks = new List<runtask>();
                for (int index = 0; index < 10; index++)
                {
                    runtask task = new runtask();
                    tasks.Add(task);
                }
                while(true)
                {
                  
                }
            }
            class runtask
            {
                Timer mytimer = new Timer();
                public runtask()
                {
                    mytimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
                    mytimer.Interval = 2000;
                    mytimer.Enabled = true;
                    
                }
                private static void OnTimedEvent(object source, ElapsedEventArgs e)
                {
                    Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
                }
            }
            
        }
    }


    jdweng

    Monday, October 15, 2012 5:11 PM
  • "Servy42, I do know how async/wait works and I do know it is very useful in my case. "

    Well the code snippets you've provided indicate otherwise.  Now that's fine; it's a brand new feature (only officially released a few months ago) that very few people are even moderately familiar with, and even fewer people are adept at using.  Even I will only claim to have a moderate understanding of it's application.  You came here to ask for help, and your response to that help seems to be, "Don't try to help me, I know what I'm doing." 

    You say, "The only question I asked is how to properly call async method in a background task."

    To that I will respond by saying, if you want to know how to use async/await I would start by actually writing out all of the code that async/await would generate.  Write out your example using continuations to tasks.  That will help you figure out both if you need async await, and which methods should be awaited on.

    Monday, October 15, 2012 5:17 PM
  • use

    LogOperation("Start async tasks.");
    Task.WaitAll(
        Task.Run(() => DoSomethingAsync()),
        Task.Run(() => DoSomethingAsync()));
    LogOperation("Done.");

    or you will have to use

    LogOperation("Start async tasks."); Task.WaitAll( async Task.Factory.StartNew(async () => await DoSomethingAsync()), async Task.Factory.StartNew(async () => await DoSomethingAsync())); LogOperation("Done.");


    i had a similar problem in my code and you will find an explanation from me there:

    http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/99a5069a-4c09-466e-a214-af43055977c0



    • Edited by Confuset Friday, November 30, 2012 6:01 PM fixed wrong code, thanks servy42
    Friday, November 30, 2012 4:53 PM
  • @confuset

    Neither you nor the OP of this thread should be using `WaitAll` at all.  The whole point of using async/await is that you don't perform blocking waits, everything is done through continuations.

    Your code snippet doesn't even compile.  

    async Task.Factory.StartNew(() => DoSomethingAsync())

    That isn't valid C# code.

    The other answer marked as the answer in your thread is the proper way of using async await, rather than the post of yours that is marked as the answer.

    Friday, November 30, 2012 5:13 PM
  • servy42: You are correct if you have a form application.  If you have a console application, you need to block in the main process inorder to keep the program running.  Without the block, the program would immediately stop.  You also need a mechanism to end the program.  the sample code I posted is correct except it is constantly running in the  loop below.  Wouldn't be smart instead of running constantly to use a WaitAll in place of the code below?

               while(true)
               
    {
                 
               
    }


    jdweng

    Friday, November 30, 2012 5:45 PM
  • servy42: You are correct if you have a form application.  If you have a console application, you need to block in the main process inorder to keep the program running.  Without the block, the program would immediately stop.  You also need a mechanism to end the program.  the sample code I posted is correct except it is constantly running in the  loop below.  Wouldn't be smart instead of running constantly to use a WaitAll in place of the code below?

               while(true)
               
    {
                 
               
    }

    In a console application, if this asynchrony makes up the entirety of the program (i.e. you're in a situation in which there is nothing keeping the `Main` method busy) then it probably means you just shouldn't be using asynchrony in the first place.  You probably should just be using blocking methods instead of async/await.  If you are using libraries that *only* provide task returning methods then perform a blocking wait on every task right away (to effectively serialize everything).  The entire point of this style of asynchrony is to keep a main thread free, and not blocked.  A console application desires the opposite state; a main thread that's always running and ends the program when it's first freed.

    Another option would be to simply create a message loop, much like what you'd see in a desktop UI application, in your console application.  See this blog post (and the proceeding two entries in that series) for a way of doing that.

    A final option is to use asynchrony as intended for a UI app but to wrap everything in a task that you do a blocking wait on.  That's what Confuset is doing.  If it's a console app it's not a terrible approach; if it's not a console app then it's likely very problematic.  Even if this works though it's going through a lot of effort to properly maintain asynchronous when you just don't need to.  (See my first paragraph; just do everything serially.)

    Obviously having a "while(true){}" is just bad.  You *really* shouldn't do that.
    • Edited by servy42 Friday, November 30, 2012 6:03 PM
    Friday, November 30, 2012 6:02 PM
  • fixed the code. thanks

    normally you should use non-blocking code for all the reasons. but, like Joel pointed out, there are situations when you can't use .WhenAll() because you have to block the thread or you simply can't add 'async' to a method (entryponts/main).

    and i basically provided a solution to the OP by using 'Task.Run' and not use 'Task.Factory.StartNew'. and left Task.WaitAll in place. changing too much code can be confusing ;) and using .WaitAll wasn't the reason for unexpected behaviour, using 'Task.Factory.StartNew' was.

    see Task.Run vs. Task.Factory.StartNew for a good explanation.

    edit: also keep in mind that 'await/asnyc' comes with an overhead..context switching/fetching etc.



    • Edited by Confuset Friday, November 30, 2012 6:16 PM
    Friday, November 30, 2012 6:13 PM
  • To the Task.Run vs Task.Factory.StartNew, if you've read that then you'll see that Run is just calling StartNew and using default values for many of the arguments. It's not like it's a fundamentally different method. That change is not important in this context. You can use either method by just making slight modifications to how you call it.

    As to the blocking calls, I've addressed that in my previous post. In most situations in which you're using asynchrony to make up the entirety of a console app it often means you just shouldn't be; you should be converting the code to using entirely blocking methods, rather than mixing and matching the two. The mix and match can end up resulting in deadlocks if you're not careful.

    As for "the overhead that comes with async/await". I'm suggesting that if you're in a console app you shouldn't be using it at all in many cases, rather than suggesting you use it more, so that would only support my case.

    • Edited by servy42 Friday, November 30, 2012 6:52 PM
    Friday, November 30, 2012 6:41 PM
  • off topic: i like this conversation, always good to learn and listen to others opinion ;)

    Task.Run vs Task.Factory.StartNew:

    i do not agree with you on that. since using 'Task.Factory.Start' without await leads to wrong, unexpected behavior. just look at the first post:

    [10] Start async tasks.
    [6] Doing something...
    [12] Doing something...
    [6] Waiting something...
    [12] Waiting something...
    [10] Done.
    [6] Doing something again...
    [14] Doing something again...

    this is just wrong.

    and using Task.Run(..) fixes that behavior and this is a big difference. (even though you could get the same result with using Task.Factory.StartNew with additional parameters.

    blocking/non-blocking:

     this doesn't really have anything to do with the code working right or wrong. and yes you should use non-blocking most of the time. but if you are doing heavy calculations in the background, which most of the time have to run sequential/ordered for some reasons and you are forced to call into the async framework, not blocking these calls leads to a lot of async/await in your code, which is not necessary and you add a lot of cpu overhead because you didn't block that one call.

    in my opinion its best to find a place in your calling hierarchy where you can start a second execution path, start a thread and block that appropriately. at least this is what i did ;)

    Friday, November 30, 2012 7:24 PM
  • The problems with the OP of this post run much deeper than the use of StartNew vs Run.  I don't disagree that it is quite flawed, that's just not one of the flaws it has.

    As I have said several times already.  If you're running in an environment where you're able to block in the first place, i.e. a console app, and you feel the need to do so, it almost always means you should be using entirely *blocking* methods throughout, rather than mixing and matching async/await.  Async/await is a very much all or nothing paradigm.  Either you need it *everywhere*, or *nowhere*.  If you have a console app, chances are it's *nowhere*.

    Friday, November 30, 2012 7:33 PM
  • in every application which uses the framework, you will run into Async-methods you will have to call. and i think its pretty fair to do async/await there, as it is normally much easier to write, read and maintain. even if you are not using it in the rest of the app for some reason. so its not really an on/off decission. but you should know what you are doing, but well, this goes with all programming and it gets much worse when it comes to asynchrony and parallelism/concurrency.
    Friday, November 30, 2012 7:53 PM
  • in every application which uses the framework, you will run into Async-methods you will have to call. and i think its pretty fair to do async/await there, as it is normally much easier to write, read and maintain. even if you are not using it in the rest of the app for some reason. so its not really an on/off decission. but you should know what you are doing, but well, this goes with all programming and it gets much worse when it comes to asynchrony and parallelism/concurrency.
    If you're writing an application that executes it's functions synchronously, but you are using a library that only exposes Task<TResult> instead of synchronous counterparts then you should just call Result on each task as soon as you first get an instance of it.  You shouldn't be awaiting it and then arbitrarily Waiting it at some point.  It creates a mishmash of very complex and hard to follow control flow.  It is certainly not simpler than just using Result right away.
    Friday, November 30, 2012 8:22 PM
  • the problem with that is, that you can't use .Result directly as this will throw you an exception because the completion is probably not done yet. so you first have to .Wait (block) or await.

    and i don't understand this on/off decision. if i for example want do download x files and after finishing download copy them somewhere else and do some stuff this is pretty easy using async and await. but if i want/have to wait for all of this to complete before going on with my code why shouldn't i block? just because i used async/await before?

    and iam pretty sure that you can write rally nasty stuff using async and await, like you can with blocking.

    my guess is that, you will see a lot of UI code using async and await and that computation intense code will try to avoid using async and await, because this will automatically clutter all over your code where it is not needed.

    Friday, November 30, 2012 9:42 PM
  • Calling "Result" on a Task that isn't complete doesn't throw an exception, it just performs a blocking wait until the task is complete and then returns the result.

    I don't see how awaiting a task only to block some containing task at a higher level would be easier than just blocking the lower level task and not even *having* a containing class.  async/await code is indeed much easier than the alternate methods *of providing functionally equivalent code*, but the whole idea is that the code should read as if it's blocking.  It's mimicking sequential code.  Such code isn't likely to be simpler or easier than code that's *actually sequential*.  

    As I've said, when you start mixing and matching it's much more complex than using just one or the other.  It makes it much harder on the reader to understand what's going on when they have to try *really* hard to figure out the control flow.  It's also *much* easier to make a mistake when you're using some of both techniques rather than one or the other.

    Friday, November 30, 2012 10:01 PM
  • mmh, maybe this was in a preview version, because i remember getting some sort of ResultNotCalculated-Exception. i can't test it right know, since my laptop is to old for win8 =)

    Saturday, December 1, 2012 12:40 AM