c# - c# Task.WhenAll 在等待完成时阻塞
问题描述
我有一个简单的 Winforms 应用程序。我想后台 TCP 连接/打印请求,并在我的代码中的设定点检查所有任务的输出。
我希望ReportOnTasks
阻止直到WaitAll
完成。请有人能解释为什么不是这样吗?我也担心我的结构不正确。
编辑,澄清我的意图:我想在收到数据后立即发送打印作业。然后继续进行其他一些数据库操作。完成所有打印操作后,我想更新 UI 以说明结果。
我试图尽可能地简化代码。也许太多了。HomeController 只是初始化一些东西。表单和文件观察器上有触发主要功能的按钮。
public class HomeController
{
public HomeController(){
MessageBox.Show("1");
oPrintController.PrintAsync("192.168.2.213", Encoding.ASCII.GetBytes("string to print"));
MessageBox.Show("2");
// Block here untill tasks are complete
ReportOnTasks();
MessageBox.Show("Report on tasks complete");
}
public async void ReportOnTasks()
{
await Task.WhenAll(oPrintController.Tasks);
foreach(Task<PrintController.PrintResult> PR in oPrintController.Tasks)
{
// do something with the result of task
}
}
}
和PrintController
public class PrintController
{
public List<Task<PrintResult>> Tasks = new List<Task<PrintResult>>();
public async void PrintAsync(string sIP, List<byte[]> lsToPrint, int iPort = 9100)
{
var s = await Task.Run(() => PrintAsync1(sIP, lsToPrint));
}
public async System.Threading.Tasks.Task<PrintResult> PrintAsync1(string sIP, List<byte[]> lsToPrint, int iPort = 9100)
{
using (TcpClient tc = new TcpClient())
{
await tc.ConnectAsync(sIP, iPort);
using (var ns = tc.GetStream())
{
foreach (byte[] btLabel in lsToPrint)
{
await ns.WriteAsync(btLabel, 0, btLabel.Length);
}
}
}
Thread.Sleep(10000);
return new PrintResult();
}
}
public class PrintResult
{
bool bSuccess = false;
}
解决方案
你没有await
调用ReportOnTasks()
此外,你不能await
在一个ctor中,因为它们不能是异步的。
根据您HomeController
的使用方式,您可以使用一个静态异步方法,该方法返回一个HomeController
由私有 ctor 创建的实例:
像这样的东西:
public class HomeController
{
//notice private - you can't new up a HomeController - you have to use `CreateInstance`
private HomeController(){
MessageBox.Show("1");
//not clear from your code where oPrintController comes from??
oPrintController.PrintAsync("192.168.2.213", Encoding.ASCII.GetBytes("string to print"));
MessageBox.Show("2");
MessageBox.Show("Report on tasks complete");
}
public static async Task<HomeController> CreateInstance() {
var homeController = new HomeController();
await homeController.ReportOnTasks();
return homeController;
}
//don't use async void! Change to Task
public async Task ReportOnTasks()
{
//not clear from your code where oPrintController comes from??
await Task.WhenAll(oPrintController.Tasks);
foreach(Task<PrintController.PrintResult> PR in oPrintController.Tasks)
{
// do something with the result of task
}
}
}
用法:
var homeControllerInstance = await HomeController.CreateInstance();
推荐阅读
- rust - 使用 Struct 的特征对象 - 错误:类型参数的数量错误
- python - 为什么我在计算波动率时得到 NaN?
- python - Python:没有 Pandas 的 csv 文件和字典
- javascript - 阻止自动回复 HTTPS 请求
- heroku - 错误“IOError:文件/.../不存在”在rails 6上的公共文件中使用sidekiq
- arrays - PowerShell - 使用带有字符串数组的管道 where-object 过滤文件名
- python - 如何将 XML 格式的表格导入 Excel 文件?
- algorithm - 使用 BST 查找基于某些属性的查询
- google-cloud-platform - GCP 虚拟机可以在我离线时运行吗?
- oracle - 具有多个表连接的 Oracle LISTAGG