IT:AD:NET:HowTo:Async

  • As a general rule async all the way down”.
  • await versus Wait(): conceptually similar - totally different. Wait() blocks the thread till completion.

const int interval = 1000;

/* The results of the following are:
Begin
Using 'Await':Bar
Using 'Await':Foo
Using 'Result':Bar
Using 'Result':Foo
Using 'Wait':Bar
But 'Wait' doesn't have a 'Result' to dump out...
Nearly...
Missing 'Await'....:Foo
End
Missing 'Await'....:Bar
*/

void Main()
{
	Console.WriteLine("Begin");
	UseAwait().Wait();
	UseResult().Wait();
	UseResult().Wait();
	UseWait().Wait();
	"----".Dump();
	InvokeUseResult().Wait();
	//Block thread:
	Task.Delay(interval).Wait();
	Console.WriteLine("Nearly...");

	//Block thread an older way:
	Thread.Sleep(interval);
	
	
	//This may continue on a background channel
	//after Main is completed (may...):
	MissingInternalAwait();
	// But this line will certainly print before
	// the above background thread completes
	Console.WriteLine("End");
}
//-----------------------------------
// Convention is to suffix async methods with 'Async':
async Task UseAwait()
{
	// Wait for results by using 'await'
	// without blocking this thread:
	var r = await FooAsync("Using 'Await'");
	r.Dump();
}

async Task InvokeUseResult(){
  // Even if you yourself use await, something further 
  // down could be blocking a thread using Result or Wait
  // which sort of defeats the purpose (it freezes UX)
  // a way to change that is use ConfigureAwait to
  // break off to a new context:
  await UseResult("forcing new context...").ConfigureAwait(false);
}
async Task UseResult(string prefix=null)
{
	// The difference between using 'await' and 'result'
	// is that Result blocks the thread.
	// so should be avoided because it gives the 
	// feeling that you're doing async calls...but
	// not really... It may give the illusion of being
	// async in a console, but in a UI thread, where there is only 
	// one UI thread that you have to "sync" back to, can 
	// freeze interaction. Hence the use of ConfigureAwait(false)
	// above
	var r = FooAsync(prefix + "Using 'Result'").Result;
	r.Dump();
}
async Task UseWait(){
	//Same for 'wait' (a thread blocking outcome), 
	//but it's used for Tasks that have no result:
	FooAsync("Using 'Wait'").Wait();
	"But 'Wait' doesn't have a 'Result' to dump out...".Dump();
}
//-----------------------------------
//Intentional error:
async Task MissingInternalAwait()
{
	// Wait for results by using 'await'
	// without blocking this thread:
	var r = FooAsync("Missing 'Await'....");
	r.Dump();
}
//-----------------------------------
async Task<string> FooAsync(string prefix)
{
	await Task.Factory.StartNew(() => Thread.Sleep(interval));
	//Use Await within a task marked as async
	await BarAsync(prefix).Dump();
	return prefix + ":" + "Foo";
}
async Task<string> BarAsync(string prefix)
{
	await  Task.Delay(interval);
	return prefix + ":" + "Bar";
}

  • /home/skysigal/public_html/data/pages/it/ad/net/howto/async/home.txt
  • Last modified: 2023/11/04 02:24
  • by 127.0.0.1