How to not wait for a long running async task method? - c#

I know it's not a good practice to use an async void. But what if I don't want to wait for a result of a long running task?
I have a scenario where I need to insert some values to the database and return a result. But I don't need to wait to finish all the insert before returning an instance of an object.
If you look at the code below, there's a method that initializes the DataService. But during the initialization part it needs to insert code description and headers to the database. I would like to return the dataService and I don't care if the code description and headers are finished inserting.
async Task<DataService> InitializeAsync()
{
_dataService = new DataService();
await _dataService.InsertCodeDescriptionAsync();
await _dataService.InserHeadersAsync();
return _dataService;
}
I think I can do that by changing InsertCodeDescriptionAsync and InsertHeadersAsync to be an async void function. But that's not good according to some articles I read. So what would be the best thing to do in this scenario?
Update:
The goal is to initialize the dataService and do the insert in the background.

Well my suggested answer is two-fold:
Simple answer: If you don't need to await a task, then don't await it.
But the consequences will be that the execution contexts of your main code and your not awaited tasks will diverge and if an exception happens in either of the methods you'll never know in your code. I suppose you call the two methods for a reason and they do something that'll eventually be needed by your code but not right away?
If so then I would suggest to still use await even if you don't need the methods to complete right away. This will however guarantee that the methods have completed at some point and the performance impact is often minimal, especially in a multi-threading scenario, since that's when the async magic kicks in and frees a lot of CPU time while waiting.
If you want to have both speed and reliability you could do something like
(DataService, Task) InitializeAsync()
{
_dataService = new DataService();
var t = Task.WhenAll(_dataService.InsertCodeDescriptionAsync(), _dataService.InserHeadersAsync());
return (_dataService, t);
}
which will give you the dataService right away but also a Task that you can use to await the completion of your initialization methods when you need them to be completed.

don't await the tasks you don't want to wait for. something like below will work for you.
Task<DataService> InitializeAsync()
{
_dataService = new DataService();
_dataService.InsertCodeDescriptionAsync();
_dataService.InserHeadersAsync();
return Task.FromResult(_dataService);
}

You could get rid of async and await altogether:
DataService Initialize()
{
_dataService = new DataService();
var fireAndForgetTask1 = _dataService.InsertCodeDescriptionAsync();
var fireAndForgetTask2 = _dataService.InsertHeadersAsync();
return _dataService;
}
This way you avoid any compiler warnings, and communicate your intent to ignore the results of the tasks to future maintainers of your code.

Related

KeyVaultClient hangs at GetSecretAsync [duplicate]

I have a multi-tier .Net 4.5 application calling a method using C#'s new async and await keywords that just hangs and I can't see why.
At the bottom I have an async method that extents our database utility OurDBConn (basically a wrapper for the underlying DBConnection and DBCommand objects):
public static async Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function)
{
string connectionString = dataSource.ConnectionString;
// Start the SQL and pass back to the caller until finished
T result = await Task.Run(
() =>
{
// Copy the SQL connection so that we don't get two commands running at the same time on the same open connection
using (var ds = new OurDBConn(connectionString))
{
return function(ds);
}
});
return result;
}
Then I have a mid level async method that calls this to get some slow running totals:
public static async Task<ResultClass> GetTotalAsync( ... )
{
var result = await this.DBConnection.ExecuteAsync<ResultClass>(
ds => ds.Execute("select slow running data into result"));
return result;
}
Finally I have a UI method (an MVC action) that runs synchronously:
Task<ResultClass> asyncTask = midLevelClass.GetTotalAsync(...);
// do other stuff that takes a few seconds
ResultClass slowTotal = asyncTask.Result;
The problem is that it hangs on that last line forever. It does the same thing if I call asyncTask.Wait(). If I run the slow SQL method directly it takes about 4 seconds.
The behaviour I'm expecting is that when it gets to asyncTask.Result, if it's not finished it should wait until it is, and once it is it should return the result.
If I step through with a debugger the SQL statement completes and the lambda function finishes, but the return result; line of GetTotalAsync is never reached.
Any idea what I'm doing wrong?
Any suggestions to where I need to investigate in order to fix this?
Could this be a deadlock somewhere, and if so is there any direct way to find it?
Yep, that's a deadlock all right. And a common mistake with the TPL, so don't feel bad.
When you write await foo, the runtime, by default, schedules the continuation of the function on the same SynchronizationContext that the method started on. In English, let's say you called your ExecuteAsync from the UI thread. Your query runs on the threadpool thread (because you called Task.Run), but you then await the result. This means that the runtime will schedule your "return result;" line to run back on the UI thread, rather than scheduling it back to the threadpool.
So how does this deadlock? Imagine you just have this code:
var task = dataSource.ExecuteAsync(_ => 42);
var result = task.Result;
So the first line kicks off the asynchronous work. The second line then blocks the UI thread. So when the runtime wants to run the "return result" line back on the UI thread, it can't do that until the Result completes. But of course, the Result can't be given until the return happens. Deadlock.
This illustrates a key rule of using the TPL: when you use .Result on a UI thread (or some other fancy sync context), you must be careful to ensure that nothing that Task is dependent upon is scheduled to the UI thread. Or else evilness happens.
So what do you do? Option #1 is use await everywhere, but as you said that's already not an option. Second option which is available for you is to simply stop using await. You can rewrite your two functions to:
public static Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function)
{
string connectionString = dataSource.ConnectionString;
// Start the SQL and pass back to the caller until finished
return Task.Run(
() =>
{
// Copy the SQL connection so that we don't get two commands running at the same time on the same open connection
using (var ds = new OurDBConn(connectionString))
{
return function(ds);
}
});
}
public static Task<ResultClass> GetTotalAsync( ... )
{
return this.DBConnection.ExecuteAsync<ResultClass>(
ds => ds.Execute("select slow running data into result"));
}
What's the difference? There's now no awaiting anywhere, so nothing being implicitly scheduled to the UI thread. For simple methods like these that have a single return, there's no point in doing an "var result = await...; return result" pattern; just remove the async modifier and pass the task object around directly. It's less overhead, if nothing else.
Option #3 is to specify that you don't want your awaits to schedule back to the UI thread, but just schedule to the thread pool. You do this with the ConfigureAwait method, like so:
public static async Task<ResultClass> GetTotalAsync( ... )
{
var resultTask = this.DBConnection.ExecuteAsync<ResultClass>(
ds => return ds.Execute("select slow running data into result");
return await resultTask.ConfigureAwait(false);
}
Awaiting a task normally would schedule to the UI thread if you're on it; awaiting the result of ContinueAwait will ignore whatever context you are on, and always schedule to the threadpool. The downside of this is you have to sprinkle this everywhere in all functions your .Result depends on, because any missed .ConfigureAwait might be the cause of another deadlock.
This is the classic mixed-async deadlock scenario, as I describe on my blog. Jason described it well: by default, a "context" is saved at every await and used to continue the async method. This "context" is the current SynchronizationContext unless it it null, in which case it is the current TaskScheduler. When the async method attempts to continue, it first re-enters the captured "context" (in this case, an ASP.NET SynchronizationContext). The ASP.NET SynchronizationContext only permits one thread in the context at a time, and there is already a thread in the context - the thread blocked on Task.Result.
There are two guidelines that will avoid this deadlock:
Use async all the way down. You mention that you "can't" do this, but I'm not sure why not. ASP.NET MVC on .NET 4.5 can certainly support async actions, and it's not a difficult change to make.
Use ConfigureAwait(continueOnCapturedContext: false) as much as possible. This overrides the default behavior of resuming on the captured context.
I was in the same deadlock situation but in my case calling an async method from a sync method, what works for me was:
private static SiteMetadataCacheItem GetCachedItem()
{
TenantService TS = new TenantService(); // my service datacontext
var CachedItem = Task.Run(async ()=>
await TS.GetTenantDataAsync(TenantIdValue)
).Result; // dont deadlock anymore
}
is this a good approach, any idea?
Just to add to the accepted answer (not enough rep to comment), I had this issue arise when blocking using task.Result, event though every await below it had ConfigureAwait(false), as in this example:
public Foo GetFooSynchronous()
{
var foo = new Foo();
foo.Info = GetInfoAsync.Result; // often deadlocks in ASP.NET
return foo;
}
private async Task<string> GetInfoAsync()
{
return await ExternalLibraryStringAsync().ConfigureAwait(false);
}
The issue actually lay with the external library code. The async library method tried to continue in the calling sync context, no matter how I configured the await, leading to deadlock.
Thus, the answer was to roll my own version of the external library code ExternalLibraryStringAsync, so that it would have the desired continuation properties.
wrong answer for historical purposes
After much pain and anguish, I found the solution buried in this blog post (Ctrl-f for 'deadlock'). It revolves around using task.ContinueWith, instead of the bare task.Result.
Previously deadlocking example:
public Foo GetFooSynchronous()
{
var foo = new Foo();
foo.Info = GetInfoAsync.Result; // often deadlocks in ASP.NET
return foo;
}
private async Task<string> GetInfoAsync()
{
return await ExternalLibraryStringAsync().ConfigureAwait(false);
}
Avoid the deadlock like this:
public Foo GetFooSynchronous
{
var foo = new Foo();
GetInfoAsync() // ContinueWith doesn't run until the task is complete
.ContinueWith(task => foo.Info = task.Result);
return foo;
}
private async Task<string> GetInfoAsync
{
return await ExternalLibraryStringAsync().ConfigureAwait(false);
}
quick answer :
change this line
ResultClass slowTotal = asyncTask.Result;
to
ResultClass slowTotal = await asyncTask;
why? you should not use .result to get the result of tasks inside most applications except console applications if you do so your program will hang when it gets there
you can also try the below code if you want to use .Result
ResultClass slowTotal = Task.Run(async ()=>await asyncTask).Result;

How(and why) can I avoid returning a void on these async methods?

EDIT: So it seems having the method return void instead of task means that exceptions are propagated on the wrong(unexpected?) context.
However, my IDE (Xamarin) is still kicking up a fuss on the line in my constructor where I call AttemptDatabseLoad()
"The statement is not awaited and execution of current method
continues before the call is completed. Consider using 'await'
operator or calling 'Wait' method"
Why is it kicking up this fuss? Surely the entire purpose of using an async method is precisely so that the program continues execution on the Main thread.
I've read a fair bit on async and await as I need to have some async data loading for an app i'm making. I've read in loads of places that it's bad practice to have an async method return void (excepting in cases of firing events) and I understand the reason why it can be good to keep a handle on the Task.
However, I can't see anything logically wrong with what I've written below so my question is twofold: Why is my current code poor practice? How should it be re-written?
private const int MAX_CONNECTION_ATTEMPTS = 10;
private int ConnectionAttempts = 0;
//Constructor
public DataLoader()
{
//First load up current data from local sqlite db
LoadFromLocal();
//Then go for an async load from
AttemptDatabaseLoad();
}
public async void AttemptDatabaseLoad()
{
while(ConnectionAttempts < MAX_CONNECTION_ATTEMPTS){
Task<bool> Attempt = TryLoad ();
bool success = await Attempt;
if (success) {
//call func to load data into program memory proper
}else{
ConnectionAttempts++;
}
}
}
//placeholder for now
public async Task<bool> TryLoad()
{
await Task.Delay(5000);
return false;
}
Constructor are meant to bring an object to it's fully constructed structure once initialized. On the other hand, async methods and constructors don't play well together, as a constructor is inherintly synchronous.
The way to get around this problem is usually to expose an initialization method for the type, which is itself async. Now, you let the caller initialize the object fully. Note this will require you to monitor the actual initialization of the method.
Async shines when you need scale. If you don't expect this to be an IO bottleneck in your application, perhaps consider using synchronous methods instead. This will give you the benefit of actually fully initializing your object once the constructor finishes execution. Although, I don't think I would initiate a call to a database via a constructor anyway:
public async Task InitializeAsync()
{
LoadFromLocal();
await AttemptDatabaseLoadAsync();
}
public async Task AttemptDatabaseLoadAsyncAsync()
{
while(ConnectionAttempts < MAX_CONNECTION_ATTEMPTS)
{
Task<bool> Attempt = TryLoad ();
bool success = await Attempt;
if (success)
{
//call func to load data into program memory proper
}
else
{
ConnectionAttempts++;
}
}
}
And call it:
var dataLoader = new DataLoader();
await dataLoader.InitializeAsync();
I understand the reason why it can be good to keep a handle on the Task.
So it seems having the method return void instead of task means that exceptions are propagated on the wrong(unexpected?) context.
One of the reasons it's good to have a Task is that you can use it to retrieve the results of the asynchronous method. And by "results", I don't just mean the return value - I mean exceptions, too. The Task represents the execution of that asynchronous method.
When an exception escapes an async Task method, it's placed on that returned task. When an exception escapes an async void method, there's no obvious place for it to go, so the actual behavior is to raise it directly on the SynchronizationContext that was current at the beginning of the async void method. This sounds odd, but it's specifically designed to emulate exceptions escaping event handlers.
Of course, if your async void method isn't an event handler (like this example), then the behavior seems very odd and surprising.
Why is it kicking up this fuss? Surely the entire purpose of using an async method is precisely so that the program continues execution on the Main thread.
I think you're misunderstanding the warning message. Since the Task represents the execution of that method, to ignore it is an error 99.9% of the time. By ignoring it, your code is saying that it doesn't care when the async method completes, what its return value is (if any), and whether or not it throws exceptions. It's extremely rare for code to not care about any of these.
How should it be re-written?
I have a blog post on how to do "async constructors". My favorite approach is the asynchronous factory method:
//Constructor
private DataLoader()
{
//First load up current data from local sqlite db
LoadFromLocal();
}
public static async Task<DataLoader> CreateAsync()
{
var result = new DataLoader();
await result.AttemptDatabaseLoadAsync();
return result;
}
However, since you're using this in a UI application, I suspect you'll eventually run into a situation where you want to call asynchronous code from your ViewModel constructor. Asynchronous factories are great for helper code (like DataLoader), but they don't work for ViewModels because the VMs need to be created immediately - the UI needs to show something now.
At the UI layer, you have to first initialize your UI to some kind of a "loading" state, and then update it to a "normal" state once the data has arrived. I prefer to use asynchronous data binding for this, as described in my MSDN article.
You can just change return type to Task (non-generic) and don't return "explicitly" from async method. The reasons why it's better to use void only on top-level functions can be found here: async/await - when to return a Task vs void?
So, it's mainly about recovery from exception in your async-void method. I hope it will help.
EDIT: One more thing - because I didn't notice that you're calling it from constructor. Please check also this answer: https://stackoverflow.com/a/23051370/580207 and this blog post: http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html
Why is my current code poor practice?
The callers of DataLoader() constructor might experience the following issues:
Code instantiating DataLoader class is not aware that load operation is still in progress after DataLoader() returns, so it cannot use the data retrieved by async AttemptDatabaseLoad().
There is no way to discover when the loaded data becomes available.
It cannot be composed into a larger asynchronous operation.
A suggested change is to store the task returned by async method in a property so that the caller can use it to wait until load is completed, or compose it into an asynchronous method.
class DataLoader
{
public DataLoader ()
{
//First load up current data from local sqlite db
LoadFromLocal();
//Then go for an async load from
this.Completion = AttemptDatabaseLoadAsync();
}
async Task AttemptDatabaseLoadAsync()
{
while(ConnectionAttempts < MAX_CONNECTION_ATTEMPTS){
Task<bool> Attempt = TryLoad ();
bool success = await Attempt;
if (success) {
//call func to load data into program memory proper
}else{
ConnectionAttempts++;
}
}
}
public Task Completion
{
get; private set;
}
}
Usage:
var loader = new DataLoader();
loader.Completion.Wait();
or:
async Task SomeMethodAsync()
{
var loader = new DataLoader();
await loader.Completion;
}

Difference between calling an async method and Task.Run an async method

I have a method in my view model
private async void SyncData(SyncMessage syncMessage)
{
if (syncMessage.State == SyncState.SyncContacts)
{
this.SyncContacts();
}
}
private async Task SyncContacts()
{
foreach(var contact in this.AllContacts)
{
// do synchronous data analysis
}
// ...
// AddContacts is an async method
CloudInstance.AddContacts(contactsToUpload);
}
When I call SyncData from the UI commands and I'm syncing a large chunk of data UI freezes. But when I call SyncContacts with this approach
private void SyncData(SyncMessage syncMessage)
{
if (syncMessage.State == SyncState.SyncContacts)
{
Task.Run(() => this.SyncContacts());
}
}
Everything is fine. Should not they be the same?
I was thinking that not using await for calling an async method creates a new thread.
Should not they be the same? I was thinking that not using await for
calling an async method creates a new thread.
No, async does not magically allocate a new thread for it's method invocation. async-await is mainly about taking advantage of naturally asynchronous APIs, such as a network call to a database or a remote web-service.
When you use Task.Run, you explicitly use a thread-pool thread to execute your delegate. If you mark a method with the async keyword, but don't await anything internally, it will execute synchronously.
I'm not sure what your SyncContacts() method actually does (since you haven't provided it's implementation), but marking it async by itself will gain you nothing.
Edit:
Now that you've added the implementation, i see two things:
I'm not sure how CPU intensive is your synchronous data analysis, but it may be enough for the UI to get unresponsive.
You're not awaiting your asynchronous operation. It needs to look like this:
private async Task SyncDataAsync(SyncMessage syncMessage)
{
if (syncMessage.State == SyncState.SyncContacts)
{
await this.SyncContactsAsync();
}
}
private Task SyncContactsAsync()
{
foreach(var contact in this.AllContacts)
{
// do synchronous data analysis
}
// ...
// AddContacts is an async method
return CloudInstance.AddContactsAsync(contactsToUpload);
}
What your line Task.Run(() => this.SyncContacts()); really does is creating a new task starting it and returning it to the caller (which is not used for any further purposes in your case). That's the reason why it will do its work in the background and the UI will keep working. If you need to (a)wait for the task to complete, you could use await Task.Run(() => this.SyncContacts());. If you just want to ensure that SyncContacts has finished when you return your SyncData method, you could using the returning task and awaiting it at the end of your SyncData method. As it has been suggested in the comments: If you're not interested in whether the task has finished or not you just can return it.
However, Microsoft recommend to don't mix blocking code and async code and that async methods end with Async (https://msdn.microsoft.com/en-us/magazine/jj991977.aspx). Therefore, you should consider renaming your methods and don't mark methods with async, when you don't use the await keyword.
Just to clarify why the UI freezes - the work done in the tight foreach loop is likely CPU-bound and will block the original caller's thread until the loop completes.
So, irrespective of whether the Task returned from SyncContacts is awaited or not, the CPU bound work prior to calling AddContactsAsync will still occur synchronously on, and block, the caller's thread.
private Task SyncContacts()
{
foreach(var contact in this.AllContacts)
{
// ** CPU intensive work here.
}
// Will return immediately with a Task which will complete asynchronously
return CloudInstance.AddContactsAsync(contactsToUpload);
}
(Re : No why async / return await on SyncContacts- see Yuval's point - making the method async and awaiting the result would have been wasteful in this instance)
For a WPF project, it should be OK to use Task.Run to do the CPU bound work off the calling thread (but not so for MVC or WebAPI Asp.Net projects).
Also, assuming the contactsToUpload mapping work is thread-safe, and that your app has full usage of the user's resources, you could also consider parallelizing the mapping to reduce overall execution time:
var contactsToUpload = this.AllContacts
.AsParallel()
.Select(contact => MapToUploadContact(contact));
// or simpler, .Select(MapToUploadContact);

How to do asynchronous web calls from within asp.net

Lets say im within an ASP.NET application, WCF or web API, part of this applications job to is contact a 3rd party over the way. Id like to do this asynchronously or rather non blocking so that the thread pool doesnt get starved. However i dont want to change all my code in the service only the bit that makes the web call.
Here is some code i have written:
public string GetSomeData()
{
Task<string> stuff = CallApiAsync();
return stuff.result; //does this block here?
}
private async Task<string> CallApiasync()
{
using (var httpClient = new HttpClient())
{
string response = await httpClient.GetStringAsync(Util.EndPoint).ConfigureAwait(false);
return response;
}
}
I thought the idea was as follows but please correct any misconceptions.
The caller of CallApi can call the method and when it hits await there is a Task created which represents some work to be done asynchronously but that will take some time. At this point the thread reaches an await returns to the thread pool to do something else ie handle a different request. Once the Task completes the await line wakes up and the code continues from there as if it was synchronous.
If this is the case why do i need to return a Task from my apimethod. The caller seems to have to call stuff.Result which implies that the task may not have finished and calling result could block ? Note i don't want to make the calling method async too as then the method that calls that would need to be async etc etc.
What is the order of event here in my code?
One other question is why did i need to set configureAwait to false? otherwise everything hangs.
Id like to do this asynchronously or rather non blocking so that the thread pool doesnt get starved. However i dont want to change all my code in the service only the bit that makes the web call.
That's not possible. In order to be truly asynchronous, you must allow async to "grow" through the code as far as it needs to. What you're trying to do is block on an asynchronous call, which won't give you any benefit (you're freeing up a thread by using async, but then you're turning around and consuming a thread by using Result).
At this point the thread reaches an await returns to the thread pool to do something else ie handle a different request.
Not quite. When an async method hits an await, it returns an incomplete Task to its caller. If the caller, in turn, awaits that task, then it returns an incomplete Task to its caller, etc. When the ASP.NET runtime receives an incomplete Task from your action/service method/whatever, then it releases the thread to the thread pool.
So, you do have to go "async all the way" to see the real benefit of async.
I have an async intro on my blog if you want a more gentle introduction, as well as an MSDN article on async best practices (one of which is: async all the way). I also have a blog post that describes the deadlock you were seeing.
The compiler handles a lot of the magic behind the async pattern for you, but syntactically, you have to tell it what you want it to do by providing a method prototype that says "ok, this is an asynchronous operation that can be awaited."
For this to happen, your method must return a Task or Task<T>.
Any Task can be awaited.
You should be VERY careful when using .Result and .Wait(), as they can block in some very unexpected circumstances, because the runtime may decide to execute your method synchronously.
You should say:
await CallApiAsync();
or, to actually take advantage of it:
Task stuff = CallApiAsync();
//More code that can happen independetly of "stuff"
await stuff;
In order to do that, your GetSomeData() function must also be marked as async, but it doesn't have to, itself, return a Task.
Finished copy of a working async version of your code:
public async string GetSomeData()
{
Task stuff = CallApiAsync();
return await stuff;
}
private async Task<string> CallApiasync()
{
using (var httpClient = new HttpClient())
{
string response = await httpClient.GetStringAsync(Util.EndPoint).ConfigureAwait(false);
return response;
}
}
Honestly, if that's all the CallApiAsync function is ever going to do, you may as well inline it, though.

Proper approach on async/await method including Lambda

I would like to show two paradigms about async programming and listen to your comments.
A.
Let's say you have created a method like the following in a library to use it from your GUI clients.
public async Task<TestObject> DoSomeWork(string aParam1, object aParam2)
{
TestObject testObj = new TestObject();
...fill in params to testObj...
await MethodCallAsync(testObj);
....do other work synchronous.....
....continue fill testObj properties...
await Task.Delay(1000) // just a delay for no reason
...continue synchronous work.....
return testObj;
}
Ok, but this will chop my GUI context into small calling pieces, right? or I don't know if from the moment you declare a method async it will create a Task for all the operations inside?
If yes then great, no problem we can just declare it async and move on with our lives.
Lets say no and I would like to take the following approach so I won't disturb the GUI at all until my whole method call finishes and take the result so do something in my calling method.
B.
Another approach would be.
public async Task<TestObject> DoSomeWork(string aParam1, object aParam2)
{
TestObject testObj = new TestObject()
..fill state params....
return await Task.Factory.StartNew((state) =>
{
//But now I need to do async/await in here
// is it a good practice to async await lambdas?
// async/await practices say it's ok as long sas it is not becoming async void
// which in our case is not.
await MethodCallAsync(testObj);
....do other work synchronous.....
....continue fill state properties...
await Task.Delay(1000) // just a delay for no reason
...continue synchronous work.....
return state; // Our state and TestObject to examine after completion
}, testObj);
}
Our problem now it's not only if we should asyncify the lambda, say you do it, it the will return a Task<Task<TestObject>> and definitely we don't want that.
You should call this up in the pipeline, most probably your GUI class.
private async void SomethingClickedOrTouched(object sender, EventArgs e)
{
await RunThisAsyncToDoYourJob();
}
private async Task RunThisAsyncToDoYourJob()
{
TestObject testObj = await myObject.DoSomeWork("param1", anotherObject);
}
It just bugs me a little and I really want into detail with async programming.
So, is A paradigm the correct approach anyway, and use the B paradigm only when the Task lambda inside code is completely synchronous?
Thank you in advance.
Regards.
The proper way to write an async method is to use ConfigureAwait(continueOnCapturedContext: false) whenever you don't need to resume on the captured context. This is normally done for all "library" code.
this will chop my GUI context into small calling pieces, right?
Yes (since you're not using ConfigureAwait).
or I don't know if from the moment you declare a method async it will create a Task for all the operations inside?
Yes, async will create a Task that represents the async method. However, the fact that there is a Task does not mean that its code is running on a background thread.
it the will return a Task<Task<TestObject>> and definitely we don't want that.
I'd like to know where everyone is getting the idea of using Task.Factory.StartNew for asynchronous tasks. Task.Run is superior if you want to run code on a background thread.
I have an async intro on my blog that you may find helpful.

Categories

Resources