Вызов асинхронной функции из функции синхронизации - PullRequest
0 голосов
/ 04 ноября 2019

У меня есть функция в консольном приложении ac #, которая вызывает асинхронную функцию (моя цель - вызвать функцию azure через консольное приложение. Эта функция отвечает за преобразование zip-файлов в csv-файлы и, конечно, я бы хотелаобрабатывать zip-файл параллельно)

Здесь вы можете найти часть моего кода:

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);


                    }); 

И у меня есть асинхронная функция:

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();
        }

Я могузапустить мой код без каких-либо ошибок, но он не обрабатывает ZIP-файлы. Но после того, как я прекращаю отладку, я начинаю обрабатывать файлы !!!

Я думаю, что-то не так с моей асинхронной функцией. У вас есть идея, почему мой код не работает правильно? Правильно ли я вызываю асинхронную функцию?

1 Ответ

2 голосов
/ 04 ноября 2019

Во-первых, когда вы вызываете асинхронный метод void, эти методы не предоставляют способа завершения сигнализации и предназначены только для обработчиков событий. Во-вторых, для параллельной обработки асинхронных методов вы используете Task.WhenAll с Select вместо Parallel.ForEach. Parallel.ForEach предназначен только для операций с процессором, а не для асинхронных задач. Наконец, вам следует использовать async вплоть до корня вашего приложения и ждать всех результатов, это будет поддерживать ваш процесс до тех пор, пока все ваши двоичные объекты не будут обработаны.

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);
    }
}
...