如何在相关集合 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;
}
我可以看到这需要异步的唯一原因是为了防止阻塞 UI 线程。 我不确定DoSomethingElse()
做什么(这是您尝试并发运行的方法吗?)以及如何将结果变量用作参数,但我觉得应该result = await CallService(zf.PathToZip);
上面的行result = CallService(zf.PathToZip);
由于当前函数被标记为异步,它将向编译器发出信号,以创建一个回调,以便在任务返回时执行,并将在那里恢复执行。 当程序命中该方法时,它不会继续执行,直到返回。 其他线程(如调用异步方法的线程)将继续执行。 要调用UploadZip()
方法,它将使用如下:
public void DoThings()
{
UploadZip("MyString");
DoSomethingElseConcurrently();
}
还请记住线程安全(竞争条件、死锁等),因为这是异步编程。 在这里使用 TPL 时有一些小事情,因为您可能会发现自己嵌套异步方法调用(就像您在这里所做的那样)。 外部异步调用不能使用 .Result()
方法,因为它会阻止该线程。 内部异步线程将尝试返回到调用它的方法,从而进入死锁。