Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# c任务在等待完成时将被阻止_C#_Multithreading_Winforms_Task - Fatal编程技术网

C# c任务在等待完成时将被阻止

C# c任务在等待完成时将被阻止,c#,multithreading,winforms,task,C#,Multithreading,Winforms,Task,我有一个简单的Winforms应用程序。我想对TCP连接/打印请求进行后台处理,并在代码中的设定点检查所有任务的输出 我希望ReportOnTasks会一直阻止,直到WaitAll完成。有人能解释一下为什么不是这样吗?我还担心我没有正确地组织这个 编辑,以澄清我的意图: 我希望在收到数据后立即发送打印作业。然后继续执行其他一些DB操作。完成所有打印操作后,我想更新UI以说明结果 我试图尽可能地简化代码。也许太多了。HomeController只是初始化了一些东西。表单和文件监视程序上有触发主要功

我有一个简单的Winforms应用程序。我想对TCP连接/打印请求进行后台处理,并在代码中的设定点检查所有任务的输出

我希望ReportOnTasks会一直阻止,直到WaitAll完成。有人能解释一下为什么不是这样吗?我还担心我没有正确地组织这个

编辑,以澄清我的意图:
我希望在收到数据后立即发送打印作业。然后继续执行其他一些DB操作。完成所有打印操作后,我想更新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
        }
    }
}
您没有等待对ReportOnTasks的调用 此外,您不能在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
        }
    }
}

通常不建议在类构造函数中执行繁重的操作,但我认为您不会更改该部分,因此为了等待ReportOnTasks完成,您需要使其同步

考虑到构造函数本身不支持async/await,所以不可能将其标记为async

话虽如此,将void reportontask标记为async并不会带来真正的性能增强。此外,由于异常处理问题,不建议将void方法标记为异步,这通常是不可能的

因此,您可以像Alex向您展示的那样推迟ReportOnTask,也可以同步地等待所有任务完成,这在ctor中是可能的

    public void ReportOnTasks()
    {
        Task.WhenAll(oPrintController.Tasks).GetAwaiter().GetResult(); //synchronously wait

        foreach(Task<PrintController.PrintResult> PR in oPrintController.Tasks)
        {
            // do something with the result of task
        }
    }

但是,我不建议使用这种方法,因为创建实例需要一段时间,而且最重要的是阻塞UI线程-这通常表明有些东西确实可疑

问题是,您试图从构造函数调用一个异步方法,它不是/不能是异步的。您应该检查这个问题:我将创建一个公共异步任务初始化{}方法来初始化类。您所说的块到底是什么意思?你是说块用户界面吗?如果是这样,那么不,异步/等待的要点是不阻塞。但是,如果你的意思是,在。。。然后直到。。。那么是的,这应该会发生。但是,ReportOnTasks是一种返回任务的方法,您没有等待此任务,因此本质上您是以一种“一劳永逸”的方式启动此任务。我希望在收到数据后立即发送打印作业。然后继续执行其他一些DB操作。一旦所有的打印操作都完成了,我想更新UI以声明这样的内容@拉塞夫·戈斯·瑟卡尔森:我想等到任务完成后再做一些事情。在Main.cs中,我有一个初始化HomeController的MainForm方法。HomeController然后在其构造函数中初始化PrintController。如果你在UI线程上调用.GetAwaiter.GetResult,它可能会导致死锁,这正是OP试图避免的,因为代码简化了。世界上没有大的电话constructor@Alex我知道这一点,但由于问题要求在ctor内阻塞,很明显,实例化HomeController的线程将被阻塞?此外,我还列出了为什么不可以这样做。。。
var homeControllerInstance = await HomeController.CreateInstance();
    public void ReportOnTasks()
    {
        Task.WhenAll(oPrintController.Tasks).GetAwaiter().GetResult(); //synchronously wait

        foreach(Task<PrintController.PrintResult> PR in oPrintController.Tasks)
        {
            // do something with the result of task
        }
    }