如何正确等待任务使用多个线程完成调用?

时间:2013-11-26 04:07:51

标签: c# multithreading delegates task invoke

下面的代码是我遇到的问题的简化示例。在表单加载时会发生什么 - For循环将在每次迭代时创建一个新任务,然后进入' if(pic.InvokeRequired)' section,但将返回For循环并继续迭代之前任何任务在调用pic.BeginInvoke()之后通过各自的方法()调用。

我想要实现的是调用完成它第二次通过method()并最终将pic.BackColor更改为Color.Blue。我想这是可能的,不是吗?我花了几个小时四处搜寻,但找不到满意的答案。

要自己运行此代码,请创建一个新的WinForms应用程序项目(我使用Visual Studio 2012)并添加一个名为' pic'的PictureBox。插入以下代码。

感谢您的帮助!

private void Form1_Load(object sender, EventArgs e)
{
    for (int i = 0; i < 5; i++)
    {
        Task task = Task.Factory.StartNew(() => method());
        task.Wait(); //Waits for task to complete before proceeding
    }
}

public delegate void delegate_method();
private void method()
{
    if (pic.InvokeRequired)
    {
        delegate_method dm = new delegate_method(() => method());
        pic.BeginInvoke(dm); //If ran once (without the loop in Form1_Load) it would call 'method()' immediately from here.
    }
    else
    {
        pic.BackColor = Color.Blue;
    }
}

1 个答案:

答案 0 :(得分:0)

我可以理解这个问题,因为在某些情况下,阻止可能比完全异步更好(尽管它更像是最后的手段)。

这里的答案取决于您的异步调用(在您调用UI线程上的操作之前在后台发生的工作的实际内容 - 我假设您选择忽略的代码部分为了简单起见)做任何UI绑定的工作。如果确实如此,那你就不幸了,使用Application.DoEvents()是最好的选择。

但是,如果没有,并且您对异步代码有足够的控制权,那么您可以做的不是尝试从任务中调用UI ,而是传递{{1将工作描述回UI线程(作为Action的{​​{1}}),然后在那里处理它的调用。

请注意,我已经简化了Task的实现,因为它不再从非UI线程调用。

警告:简化的代码,不适合生产。

Result