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

C# 如何在相关集合C之间添加异步切换#,c#,.net,asynchronous,C#,.net,Asynchronous,我有一个项目,我需要通过id从数据库收集文件,压缩这些文件,将压缩后的文件上传到第三方web服务,并对响应进行处理。我正在使用Parallel.ForEach来尝试并实现这一点,但在异步运行时遇到了问题,我甚至不确定这是否是实现这一点的最佳方法。有没有一种方法可以更高效地异步运行 public async Task<string> UploadZip(string courseID) { string result = string.empty;

我有一个项目,我需要通过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;
        }
public async Task UploadZip(字符串courseID)
{
字符串结果=string.empty;
ids=courseID.Split(',).ToList();
ConcurrentStack zipPaths=新的ConcurrentStack();
Parallel.ForEach(id,(id)=>
{
files=rep.GetFiles(id);
ZipFile zf=新ZipFile(文件);
zipPaths.Push(zf.ZipFilePath);
尝试
{
而(zipPaths.Count>0)
{
文件持有人fh;
if(文件持有者.TryPop(输出fh))
{
FileInfo file=新的FileInfo(fh.EndPoint);
if(file!=null&&file.Length>0)
{
//字符串fileName=Path.GetFileName(Path);
结果=调用服务(zf.PathToZip);
DoSomethingElse-oSomethingElse=新的DoSomethingElse(结果、id、版本);
}                             
}
}
}
捕获(例外情况除外)
{
System.Diagnostics.Debug.WriteLine(string.Concat(“HomeController行123”,“错误”,例如Message,DateTime.Now.TimeOfDay));
}
ITermExtractorContent结果=新术语extractorcontent();
});
返回输出;
}
专用静态异步任务调用服务(字符串pathToZip)
{
使用(var client=new HttpClient())
{
//客户端的标题
尝试
{
使用(var content=new MultipartFormDataContent())
{
使用(var stream=newfilestream(路径,FileMode.Open,FileAccess.Read,FileShare.ReadWrite))
{
使用(var fileContent=newstreamcontent(流))
{
fileContent.Headers.Add(“内容处置”,“表单数据;名称=\”文件\“,”文件名=\”+路径.GetFileName(路径)+“\”);
Add(fileContent,“file”,Path.GetFileName(pathToZip));
使用(
var消息=
等待client.PostAsync(baseEndpoint,content))
{
output=wait message.Content.ReadAsStringAsync();
}
}
}
}//终端使用
}
捕获(例外情况除外)
{
对数(ex);
}
}//使用(var client=new HttpClient())
返回输出;
}

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

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

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

没有理由对CPU绑定的操作使用异步。异步基本上是一种防止线程在等待外部源时无所事事的方法。你的代码做了很多工作,这正是线程的用途;这意味着您的代码不是真正的异步。您一定收到了一个编译器警告,说明了相同的情况。@ErikPhilips,但我希望有两个进程1。一个用于获取文件并对其进行压缩2。而另一个则采取压缩文件,上传,等待响应。除非我错了,否则1所花的时间应该少于2,因此基本上需要两个线程。@SriramSakthivel这是正确的。我对.NET中的TPL非常陌生。我在UI中使用进度条,所以我肯定不想阻止它。