This question already has answers here:
Difference between returning and awaiting a Task in an async method [duplicate]
(3 answers)
Closed 8 years ago.
Suppose I have below code:
static void Main(string[] args)
{
println("begin s");
Task<int> s = CaculateSometingAsync();
println("begin s1");
Task<int> s1 = CaculateSometingAsync1();
println(s.Result.ToString());
println(s1.Result.ToString());
}
static async Task<int> CaculateSometingAsync()
{
return await Task.Factory.StartNew<int>(() =>
{
Thread.Sleep(1000);
return 100;
});
}
static Task<int> CaculateSometingAsync1()
{
return Task.Factory.StartNew<int>(() =>
{
Thread.Sleep(1000);
return 200;
});
}
The result is as follow:
16:55:38 begin s
16:55:38 begin s1
16:55:39 100
16:55:39 200
What I know about these two functions is that they have the same behavior.
Both they create one thread-pool thread to run the task.
Both
Task<int> s = CaculateSometingAsync();
and
Task<int> s1 = CaculateSometingAsync1();
don't block the main thread.
So is there any difference between this two functions?
The difference is the way you're using it.
In the first one (CaculateSometingAsync) you're declaring it as asynchronous, and then you await inside it until it's done. You then return whatever it returns.
In your second one (CaculateSometingAsync1) you just use it as a "fire and forget" kind of things, so it goes away, waits, and returns straightto where you called it from.
(and why do you use a method println to print the string ? :) )
you await inside the CaculateSometingAsync but could await on s as the method is declared async, where as you could not await on s1 as CaculateSometingAsync1 is not declared async. The way you are using the keywords means there is no difference in bahviour
Related
This question already has answers here:
How and when to use ‘async’ and ‘await’
(25 answers)
Call asynchronous method in constructor?
(15 answers)
How Async and Await works
(4 answers)
Closed 4 years ago.
I have a question about both keywords (Async and Await)
Their main goal is to make more than one method to be done at the same time as i understood, so for example if i'm going to do a long task which will prevent the main task from being executed in that case i have to use (Async and Await).
But when I tried it in two different programs that do the same thing i found that the execution is the same w/o using (Async and Await)
first one
class Async
{
public Async()
{
main();
}
public async void main()
{
Console.WriteLine("Main Thread....");
await SlowTask();
Console.WriteLine("Back To Main Thread");
}
public async Task SlowTask()
{
Console.WriteLine("Useless Thread....");
for (int i = 0; i < 1000000; i++)
{
// TODO
}
Console.WriteLine("Finished Useless Thread....");
}
}
and the second
class NoAsync
{
public NoAsync()
{
main();
}
public void main()
{
Console.WriteLine("Main Thread....");
SlowTask();
Console.WriteLine("Back To Main Thread");
}
public void SlowTask()
{
Console.WriteLine("Useless Thread....");
for (int i = 0; i < 1000000; i++)
{
// TODO
}
Console.WriteLine("Finished Useless Thread....");
}
}
the execution of both are exactly the same, from what i understood that when using (Async and Await) both main and SlowTask will execute at the same time without waiting for one to end so the other start to execute but that doesn't happen.
What's wrong i've made or i'm miss-understanding Asynchronous in c# ?
Kind regards.
I'd expect the execution of both to be the same. The issue is the latter, you have a misunderstanding of async in C#.
In short, when you await something in an async method, that thread is freed up to go do other stuff, until the awaited task finishes. But the program does not continue executing the next line until the awaited method completes. That would be bananas. You're thinking more of a background worker.
This can be handy, for example, when you are doing I/O and want a thread to be available to field http requests in the meantime. There is an abundance of reading material on this already. Here is a more in-depth answer
The execution should be exactly the same, they are logically consistent programs. There's likely not even a single task switch given your whole program is merely incrementing a counter variable.
This question already has answers here:
Parallel.ForEach and async-await [duplicate]
(4 answers)
Parallel foreach with asynchronous lambda
(10 answers)
Closed 12 days ago.
I was reading this post about Parallel.ForEach where it was stated that "Parallel.ForEach is not compatible with passing in a async method."
So, to check I write this code:
static async Task Main(string[] args)
{
var results = new ConcurrentDictionary<string, int>();
Parallel.ForEach(Enumerable.Range(0, 100), async index =>
{
var res = await DoAsyncJob(index);
results.TryAdd(index.ToString(), res);
});
Console.ReadLine();
}
static async Task<int> DoAsyncJob(int i)
{
Thread.Sleep(100);
return await Task.FromResult(i * 10);
}
This code fills in the results dictionary concurrently.
By the way, I created a dictionary of type ConcurrentDictionary<string, int> because in case I have ConcurrentDictionary<int, int> when I explore its elements in debug mode I see that elements are sorted by the key and I thought that elenents was added consequently.
So, I want to know is my code is valid? If it "is not compatible with passing in a async method" why it works well?
This code works only because DoAsyncJob isn't really an asynchronous method. async doesn't make a method work asynchronously. Awaiting a completed task like that returned by Task.FromResult is synchronous too. async Task Main doesn't contain any asynchronous code, which results in a compiler warning.
An example that demonstrates how Parallel.ForEach doesn't work with asynchronous methods should call a real asynchronous method:
static async Task Main(string[] args)
{
var results = new ConcurrentDictionary<string, int>();
Parallel.ForEach(Enumerable.Range(0, 100), async index =>
{
var res = await DoAsyncJob(index);
results.TryAdd(index.ToString(), res);
});
Console.WriteLine($"Items in dictionary {results.Count}");
}
static async Task<int> DoAsyncJob(int i)
{
await Task.Delay(100);
return i * 10;
}
The result will be
Items in dictionary 0
Parallel.ForEach has no overload accepting a Func<Task>, it accepts only Action delegates. This means it can't await any asynchronous operations.
async index is accepted because it's implicitly an async void delegate. As far as Parallel.ForEach is concerned, it's just an Action<int>.
The result is that Parallel.ForEach fires off 100 tasks and never waits for them to complete. That's why the dictionary is still empty when the application terminates.
An async method is one that starts and returns a Task.
Your code here
Parallel.ForEach(Enumerable.Range(0, 100), async index =>
{
var res = await DoAsyncJob(index);
results.TryAdd(index.ToString(), res);
});
runs async methods 100 times in parallel. That's to say it parallelises the task creation, not the whole task. By the time ForEach has returned, your tasks are running but they are not necessarily complete.
You code works because DoAsyncJob() not actually asynchronous - your Task is completed upon return. Thread.Sleep() is a synchronous method. Task.Delay() is its asynchronous equivalent.
Understand the difference between CPU-bound and I/O-bound operations. As others have already pointed out, parallelism (and Parallel.ForEach) is for CPU-bound operations and asynchronous programming is not appropriate.
If you already have asynchronous work, you don't need Parallel.ForEach:
static async Task Main(string[] args)
{
var results = await new Task.WhenAll(
Enumerable.Range(0, 100)
Select(i => DoAsyncJob(I)));
Console.ReadLine();
}
Regarding your async job, you either go async all the way:
static async Task<int> DoAsyncJob(int i)
{
await Task.Delay(100);
return await Task.FromResult(i * 10);
}
Better yet:
static async Task<int> DoAsyncJob(int i)
{
await Task.Delay(100);
return i * 10;
}
or not at all:
static Task<int> DoAsyncJob(int i)
{
Thread.Sleep(100);
return Task.FromResult(i * 10);
}
This question already has an answer here:
EF6 two contexts vs. single context with two awaits
(1 answer)
Closed 4 years ago.
After going through a lot of articles and videos i am still having problem with the asynchronous programming.I am working on a project where in service layer I have created all the methods as async. All of the return Task <T> or Task (I made sure not to return void).
Now to the issue. My Api calls async methods which internally calls other async methods which may even call other async methods. So I await every time I encounter an async method.
The downside with this approach, I think, is that cause I am awaiting for result every time I encounter async it will take a lot of time. For ex:
public async Task<xyz> DoMainTask(int ActionId, int ItemId, int UserId)
{
await DoTask1(ActionId,ItemId,UserId); 3 sec
await DoTask2(ActionId,ItemId,UserId); 3 sec
await DoTask3(ActionId,ItemId,UserId); 3 sec
}
So I don't want to wait for 9 sec because all tasks here are independent of each other.
I want to do something like:
public async Task<xyz> DoMainTask(int ActionId, int ItemId, int UserId)
{
List<Task> lst = new List<Task>();
t1= DoTask1(ActionId,ItemId,UserId);
lst.Add(t1);
t2 = DoTask2(ActionId,ItemId,UserId);
lst.Add(t2);
t3 = DoTask3(ActionId,ItemId,UserId);
lst.Add(t3);
await Task.WhenAll(lst);
// do some work
return xyz;
}
Which will probably take around 5-6 sec. How do I do this?
Whenever I try to use 2nd approach it get error:
A second operation started on this context before a previous asynchronous operation completed
DoTask1 is defined as:
public async Task DoTask1 (int ActionId, int ItemId, int UserId)
{
try
{
DailyActivityPoint dailyActivityPoint = new DailyActivityPoint()
{
ActionId = ActionId,
CreatedDate = DateTime.Now,
ItemId = ItemId,
UserId = UserId,
PointsAccumulated = await GetPointsAwardedForAction(ActionId)
};
_entities.DailyActivityPoints.Add(dailyActivityPoint);
await _entities.SaveChangesAsync();
}
catch (Exception ex)
{
}
}
inside DoTask1 I am also calling an async method.
How can it be done and what's the best practice?
I believe you are encountering a thread-safety concern as described here. If so, you'll need to be sure that for each 'awaitable' that reaches into EF it is using its own DbContext instance.
So, be sure you aren't using a DbContext singleton; instantiate a new one as you go if you can or get tricky with a container like he does in the link (containers are your friends)
Maybe you should use this guideline in writing your asynchronous methods
Guideline:
Write the method the normal way you would write a conventional method, then convert it to an async method.
Use the async keyword in the method declaration.
public async Task<int> ExampleMethodAsync()
{
// . . . .
}
Use the await keyword in the code calling an asynchronous process/method.
int resultValue = await ExampleMethodAsync();
Note: await can only be used in an async method modified by the async keyword.
Use one of the correct return types in the async method in order to get results
return types for an async method need to be one of the following:
Task if your method has a return statement in which the operand has type TResult.
Task if your method has no return statement or has a return statement with no operand.
void if you're writing an async event handler.
Adding the “Async” suffix at the end of the calling method name. This is not required but is considered
a convention for writing async methods in C#.
public async Task<int> ExampleCallingMethodAsync()
{
// . . . .
}
Include at least one await expression in the async method code.
The suspension of an async method at an await expression doesn't
constitute an exit from the method, and finally blocks don’t run.
public async Task<int> ExampleMethodAsync()
{
//some code
string pageContents = await client.GetStringAsync(uri);
//some more code
return pageContents.Length;
}
Note:
You have to adjust what your async method is returning. The object being returned has to match the type Task<T> of your async method
If an async method doesn’t use an await operator to mark a suspension point, the method
executes as a synchronous method does, despite the async modifier. The compiler issues a
warning for such methods.
Below is a typical method converted to an asynchronous method
Example
private void WebPage(string someURI)
{
WebClient webClient = new WebClient();
string pageContent = webClient.DownloadString(someURI);
Console.WriteLine(pageContent);
}
changed to:
private async void WebPageAsync(string someURI)
{
WebClient webClient = new WebClient();
string pageContent = await webClient.DownloadStringTaskAsync(someURI);
Console.WriteLine(pageContent);
}
I hope this was helpful?
This question already has answers here:
Async/await and parallel in C# [closed]
(1 answer)
Run two async tasks in parallel and collect results in .NET 4.5
(6 answers)
Closed 5 years ago.
Can you briefly explain me why the first two rows of this code are not running parallel? How could I make it work paralell?
SensorLeft and SensorRight are of the same class, and Distance is a public property of it which needs some time to be calculated when calling its get method.
What am I doing wrong? Should I make the Distance calculation as an async function instead to be right?
public async void GetDistance()
{
await Task.Run(() => LeftDistance = SensorLeft.Distance);
await Task.Run(() => RightDistance = SensorRight.Distance);
Distance = RightDistance < LeftDistance ? RightDistance:LeftDistance;
}
When the compiler encounters await keyword it will automatically schedule a task in task scheduler. The operation waits (in a non-blocking manner) for the task to complete before continue to do the rest of the code block.
To make your code run in parallel you need to modify it into
public async Task GetDistance()
{
var leftDTask = Task.Run(() => LeftDistance = SensorLeft.Distance);
var rightDTask= Task.Run(() => RightDistance = SensorRight.Distance);
await Task.WhenAll(leftDTask,rightDTask);
Distance = RightDistance < LeftDistance ? RightDistance:LeftDistance;
}
Task.WhenAll has an overload to return Task<TResult[]> Task.WhenAll<TResult[]>. and you can replace your code into
public async Task GetDistance()
{
var leftDTask = Task.Run(() => SensorLeft.Distance);
var rightDTask= Task.Run(() => SensorRight.Distance);
var results= await Task.WhenAll(leftDTask,rightDTask);
Distance = Math.Min(results[0],results[1]);
}
However, this is not a good solution. If you want the get distance truly asynchronous, you should make an asynchronous get method rather wrap it into Task.Run.
This question already has answers here:
Await on a completed task same as task.Result?
(2 answers)
Closed 6 years ago.
I writing a small example to get value 5 in method TestMethod, I have 2 ways to do that:
static async Task<int> TestMethod()
{
await Task.Delay(0);
return 5;
}
static async Task Caller()
{
Task<int> test = TestMethod();
int i = await test;
Console.WriteLine("i: " + i);
int k = test.Result;
Console.WriteLine("k: " + k);
}
The output:
i: 5
k: 5
So, my questions are: what's the difference between await test and test.Result? And when to use await test/test.Result?
First version
static void Caller()
{
Task<int> test = TestMethod();
int k = test.Result;
Console.WriteLine("k: " + k);
}
In this version the async keyword would be obsolete. This is a synchronous method. The executing thread blocks at test.Result until the task has finished.
Second version
static async Task Caller()
{
Task<int> test = TestMethod();
int i = await test;
Console.WriteLine("i: " + i);
}
This is a (kind of) asynchronous version (it's not really asynchron, it's just a synchronous method run on a different thread). The difference to the first version is that the compiler builds a state machine for this.
So the control flow of the executing thread is returned to the caller of this method when await test is reached.
When the task has finished, the execution of this method is resumed at Console.WriteLine (or more precisely at the assignment to i).
For more information about what the compiler does you can read for example this.
The second version is useful if you have a longer running task that you need to execute from an UI. Since the control is returned to the caller while awaiting the task, the UI thread is not blocked and your application stays responsive.
Task.Result is equivalent to Task.Wait Method which blocks synchronously until the task is complete.
await on the other hand waits asynchronously till the task is completed.
If you can await is better.