如何在相关集合 C# 之间添加异步切换

本文关键字:添加 之间 异步 集合 | 更新日期: 2023-09-27 18:35:21

>我有一个项目,我需要按 id 从数据库中收集文件,压缩这些文件,将压缩文件上传到第三方 Web 服务,并对响应执行一些操作。 我正在使用 Parallel.ForEach 来尝试完成此操作,但我无法让它异步运行,我什至不确定这是执行此操作的最佳方法。有没有办法异步运行,更有效地运行它?

    public async Task<string> UploadZip(string courseID)
    {
         string result = string.empty;
         ids = courseID.Split(',').ToList();
         ConcurrentStack<string> zipPaths  = new ConcurrentStack<string>();
        Parallel.ForEach(ids, (id) =>
         {
             files = rep.GetFiles(id); 
            ZipFiles zf = new ZipFile(files);       
            zipPaths.Push(zf.ZipFilePath);
             try
             {
                 while (zipPaths.Count > 0)
                 {
                     FileHolder fh;
                     if (fileHolder.TryPop(out fh))
                     {
                             FileInfo file = new FileInfo(fh.EndPoint);
                             if (file != null && file.Length > 0)
                             {
                                 // string fileName = Path.GetFileName(path); 
                                result = CallService(zf.PathToZip);
                                 DoSomethingElse oSomethingElse = new DoSomethingElse(result, id, version);
                             }                             
                     }
                 }
             }
             catch (Exception ex)
             {
                 System.Diagnostics.Debug.WriteLine(string.Concat("HomeController line 123","error ",ex.Message, DateTime.Now.TimeOfDay));
             }
             ITermExtractorContent result = new TermExtractorContent();
         });

        return output;
    }
     private static async Task<string> CallService(string pathToZip)
        {
            using (var client = new HttpClient())
            {
               //headers for client
                try
                {
                    using (var content = new MultipartFormDataContent())
                    {
                        using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        {
                            using (var fileContent = new StreamContent(stream))
                            {
                                fileContent.Headers.Add("Content-Disposition", "form-data; name='"file'"; filename='"" + Path.GetFileName(path) + "'"");
                                content.Add(fileContent, "file", Path.GetFileName(pathToZip));
                                using (
                                   var message =
                                       await client.PostAsync(baseEndpoint, content))
                                {
                                    output = await message.Content.ReadAsStringAsync();
                                }
                            }
                        }
                    }//end using
                }
                catch (Exception ex)
                {
                    log(ex);
                }
            }// using (var client = new HttpClient())
            return output;
        }

如何在相关集合 C# 之间添加异步切换

我可以看到这需要异步的唯一原因是为了防止阻塞 UI 线程。 我不确定DoSomethingElse()做什么(这是您尝试并发运行的方法吗?)以及如何将结果变量用作参数,但我觉得应该result = await CallService(zf.PathToZip);上面的行result = CallService(zf.PathToZip); 由于当前函数被标记为异步,它将向编译器发出信号,以创建一个回调,以便在任务返回时执行,并将在那里恢复执行。 当程序命中该方法时,它不会继续执行,直到返回。 其他线程(如调用异步方法的线程)将继续执行。 要调用UploadZip()方法,它将使用如下:

public void DoThings()
{
    UploadZip("MyString");
    DoSomethingElseConcurrently();
}

还请记住线程安全(竞争条件、死锁等),因为这是异步编程。 在这里使用 TPL 时有一些小事情,因为您可能会发现自己嵌套异步方法调用(就像您在这里所做的那样)。 外部异步调用不能使用 .Result() 方法,因为它会阻止该线程。 内部异步线程将尝试返回到调用它的方法,从而进入死锁。