Reputation: 13965
Forgive the blatant newbie question. There is something about async and await that I am not grasping.
In order for a method to be async, it must await a return from task/method that is also async. Correct? But at some point, won't there have to be a task that isn't async or won't await anything?
I've been reading tutorials like these two:
https://msdn.microsoft.com/en-us/magazine/hh456401.aspx
https://msdn.microsoft.com/en-us/library/mt674882.aspx
And I've been looking at a lot of other threads here. But there is still something I don't understand. I'll try and give a simple example. Let's say I want to write a value to a column in a database:
public async Task<SimpleObject> ExecuteAsync(int rowID, string value)
{
return await WriteToDB(int rowID, string value);
}
So far so good. But, here's where I get lost:
public async Task<SimpleObject> WriteToDB(int rowID, string value)
{
var dataRow = context. /// use linq to get a row with rowID
dataRow.SomeColumn = value
context.SaveChanges();
var simpleObject = new SimpleObject();
simpleObject.success = true;
return simpleObject;
}
public class SimpleObject
{
public bool success {get;set;}
}
I am very politely informed by VS that my method WriteToDB()
lacks await
and will run synchronously. I can still compile, and there won't be a runtime error. But, I can't figure out how to use await
inside WriteToDB()
.
Upvotes: 4
Views: 295
Reputation: 457362
I'll try and give a simple example.
As others have noted, the simple answer for the simple example is "use SaveChangesAsync
instead of SaveChanges
".
To answer the broader question of "how do I start using async", the best approach is:
await
. In this example, change SaveChanges
to await SaveChangesAsync
.async
, and it will also give you the correct return type to use. In this example, the compiler will instruct you to change SimpleObject WriteToDB(..)
to async Task<SimpleObject> WriteToDBAsync(..)
.Repeat steps (2) and (3) until your application compiles. In this example, step (2) will change the call return WriteToDB(int rowID, string value);
to return await WriteToDBAsync(int rowID, string value);
and step (3) will change SimpleObject Execute(..)
to async Task<SimpleObject> ExecuteAsync(..)
.
It's much easier to apply async
/await
in this way, starting at the lowest levels and growing from there.
But at some point, won't there have to be a task that isn't async or won't await anything?
Yes. The lowest-level methods are generally implemented by TaskFactory.FromAsync
or TaskCompletionSource<T>
.
Upvotes: 1
Reputation: 3835
EntityFramework support async query and save operations such as SaveChangesAsync and ToListAsync, these async methods follow the "Task-based Asynchronous Pattern" and return Task
or Task<T>
that you can await.
You can rewrite your code to preform the querying and saving in an async way like this:
public async Task<SimpleObject> WriteToDB(int rowID, string value)
{
var dataRow = await context.table.SingleAsync(item =>item.Id = /*some value*/);
dataRow.SomeColumn = value
await context.SaveChangesAsync();
var simpleObject = new SimpleObject();
simpleObject.success = true;
return simpleObject;
}
Upvotes: 2
Reputation: 3432
You need to use the .SaveChangesAsync method.
public async Task<SimpleObject> WriteToDB(int rowID, string value)
{
var dataRow = context.
dataRow.SomeColumn = value
await context.SaveChangesAsync(); //change this line
var simpleObject = new SimpleObject();
simpleObject.success = true;
return simpleObject;
}
Upvotes: 3