Reputation: 27
I just started learning about async/await.
There is this article of Stephen Cleary: https://blog.stephencleary.com/2013/11/there-is-no-thread.html
I don't know much about I/O but... Can someone explain me how can I apply the async/await logic for an operation that doesn't use I/O?
Let's say we have a string[]
and want to reverse all the strings in this array.
async Task<string> ReverseAsync(string s)
{
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
Then I want to "parallelly" call this method for each element in the array. I understand that a code like this will not be a valid, but how can it be implemented using async/await?
Upvotes: 1
Views: 601
Reputation:
Can someone explain me how can I apply the async/await logic for an operation that doesn't use I/O?
You can use the new async/await
in .NET to simplify concurrent operations without all the tedius mucking about of spinning up potentially expensive threads. async/await
can be used irrespective of whether the operation is CPU-bound or IO-bound.
The syntax is mostly the same except that for a CPU-bound operation you generally explicity call Task.Run()
or a version thereof. TasK
can be a thought of as a high level construct to represent concurrent operations and not a synonym for Thread
. Task.Run
will execute code in one of the re-usable threads in the thread-pool which most likely is already running. Once your operation is complete it is returned to the pool.
e.g.
await Task.Run (() => CalculatePrimeNumbersAsync (10000));
In your scenario you should try to call Task.Run() as close as you can to the top of the callstack. This makes your code:
Then I want to "parallelly" call this method for each element in the array. I understand that a code like this will not be a valid, but how can it be implemented using async/await?
There is probably not much you can do to change the implementation, however you can certainly make use of concurrency by the way you call the method.
So given your code of:
async Task<string> ReverseAsync(string s)
{
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
You would call it like so (let's assume it's a button click handler in WinForms):
async void OnButtonClicked (object sender, System.EventArgs e)
{
var reversed = await Task.Run(() => ReverseString ("Miss Piggy is a Muppet"));
}
Note again we use Task.Run()
because the client code knows that ReverseString
is CPU-bound. Don't use Task.Run() if you are going to call something I/O bound such as WCF or Entity Framework.
Upvotes: 5
Reputation: 19149
use Parallel.ForEach to execute method and reverse many strings in array. i suggest you to process strings in batch, like 10 by 10 or 100 by 100 depending on size of strings. Because overhead of scheduling a thread from thread pool for small tasks is a lot. When you batch items, you will have large enough tasks and this overhead becomes negligible.
int batchSize = 10;
Parallel.ForEach(array.Select((x,i) => new {value = x, index= i})
.GroupBy(a => a.index/batchSize),
(item) =>
{
array[item.index] = item.value.Reverse();
});
Upvotes: 1