Reputation: 3057
I have a function in a c# console application, which calls an async function (My aim is to call an azure function via a console application. This function is responsible for converting zip files to csv files and of course I would like to process the zip file in parallel)
Here you can find a section of my code:
Parallel.ForEach(blobs, (currentblob) =>
{
string FileUrl = currentblob.Uri.ToString();
string FileName = currentblob.Uri.Segments.Last();
//string content = "{ \"fileUri\": \""+ currentblob.Uri.ToString()+ "\" , \"fileName\": \""+ currentblob.Uri.Segments.Last()+"\"}";
Console.WriteLine(currentblob.Uri + " #### " + currentblob.Uri.Segments.Last());
var values = new Dictionary<string, string>
{
{ "fileUri", currentblob.Uri.ToString() },
{ "fileName", currentblob.Uri.Segments.Last() }
};
var content = new FormUrlEncodedContent(values);
string baseURL = @"https://<afu>.azurewebsites.net/api/process_zip_files_by_http_trigger?code=45"; ;
//string urlToInvoke = string.Format("{0}&name={1}", baseURL, FileUrl, FileName);
Run(baseURL, content);
});
And I have an async function:
public static async void Run(string i_URL,FormUrlEncodedContent content)
{
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsync(i_URL,content);
string responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
Console.ReadLine();
}
I can run my code without any errors, but it doesn't process zip files. But after I stop debugging then I it starts to process the files!!!
I think something is wrong with my async function. Do you have any idea why my code doesn’t work correctly? Do I call my async function correctly?
Upvotes: 1
Views: 119
Reputation: 7091
First, your calling an async void method, these methods provide no way of signalling completion and are only intended for event handlers. Second, to process async methods in parallel you use Task.WhenAll
with a Select
instead of Parallel.ForEach
. Parallel.ForEach
is only intended for CPU bound operations and not asynchronous tasks. Finally, you should then use async all the way up to the root of your application and await all results, this will keep your process alive until all your blobs have been handled.
class Program
{
private static HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
var blobs = new List<Blob>();
await ProcessBlobs(blobs);
Console.ReadLine();
}
public static async Task ProcessBlobs(IEnumerable<Blob> blobs)
{
var tasks = blobs.Select(currentblob =>
{
string FileUrl = currentblob.Uri.ToString();
string FileName = currentblob.Uri.Segments.Last();
//string content = "{ \"fileUri\": \""+ currentblob.Uri.ToString()+ "\" , \"fileName\": \""+ currentblob.Uri.Segments.Last()+"\"}";
Console.WriteLine(currentblob.Uri + " #### " + currentblob.Uri.Segments.Last());
var values = new Dictionary<string, string>
{
{ "fileUri", currentblob.Uri.ToString() },
{ "fileName", currentblob.Uri.Segments.Last() }
};
var content = new FormUrlEncodedContent(values);
string baseURL = @"https://<afu>.azurewebsites.net/api/process_zip_files_by_http_trigger?code=45"; ;
//string urlToInvoke = string.Format("{0}&name={1}", baseURL, FileUrl, FileName);
return RunAsync(baseURL, content);
});
await Task.WhenAll(tasks);
}
public static async Task RunAsync(string i_URL, FormUrlEncodedContent content)
{
var response = await client.PostAsync(i_URL, content);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
}
}
Upvotes: 3