我有 2 个类 Main.cs 和 Processing.cs(简称 P 和 M)类 M 调用 P 传递一个 html 链接,P 在 tern 下载,转换为 Base64,重命名并保存文件然后返回一个将字符串返回给 M,现在我需要 M 等到所有这些都完成才能继续,但我无法做到。
我将 lambda 表达式与事件处理程序一起使用,以便能够在该函数中执行所有操作,而不是为事件触发器使用单独的函数,因此我能够返回带有 Base64 转换文件的字符串,但它只是返回空字符串,不要等到它被分配。
我以为调用 taskA.Wait() 会让它等待所有处理完成,但事实并非如此
如果有人有任何想法,我将不胜感激。
Main.cs 的调用是这样的:
Processing processing = new processing();
String _link = “http://www.something.com”;
var ResultBase64_Val = processing.FileToBase64(_link).Result;
在 Processing.cs 中,函数是:
public async Task<String> FileToBase64(String filePath)
{
String convertedFile = "";
WebClient client = new WebClient();
Task taskA = Task.Factory.StartNew(() => client.OpenReadCompleted += async (object sender, OpenReadCompletedEventArgs e) =>
{
byte[] buffer = new byte[e.Result.Length];
buffer = new byte[e.Result.Length];
await e.Result.ReadAsync(buffer, 0, buffer.Length);
convertedFile = Convert.ToBase64String(buffer);
});
client.OpenReadAsync(new Uri(filePath));
taskA.Wait();
return convertedFile;
}
谢谢, 鲍勃
最佳答案
您的代码的问题在于,以 Task.Factory.StartNew
开始的任务会立即完成,远早于 OpenReadCompleted
在未来某个时间触发。也就是说,用 Task.Run
或 Task.Factory.StartNew
包装一个自然异步的 API,比如 OpenReadAsync
无论如何都不是一个好主意。即使您以某种方式等待事件,或使用同步 OpenRead
,您也会浪费池线程。
有新的WebClient.OpenReadTaskAsync
方法:
public async Task<String> FileToBase64(String filePath)
{
using (var client = new WebClient())
using (var stream = await client.OpenReadTaskAsync(new Uri(filePath)))
{
// use stream.ReadAsync
}
}
我还推荐 HttpClient
而不是 WebClient
,前者支持并行的多个 HTTP 请求:
using System.Net.Http;
// ...
public async Task<String> FileToBase64(String filePath)
{
using (var client = new HttpClient())
using (var response = await client.GetAsync(filePath))
using (var stream = await response.Content.ReadAsStreamAsync())
{
return string.Empty;
// use stream.ReadAsync
}
}
关于c# - 在事件处理程序上使用 lambda exp 时如何等待多个任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21867690/