下面的代码是我遇到的问题的简化示例。在表单加载时会发生什么 - 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;
}
}
答案 0 :(得分:0)
我可以理解这个问题,因为在某些情况下,阻止可能比完全异步更好(尽管它更像是最后的手段)。
这里的答案取决于您的异步调用(在您调用UI线程上的操作之前在后台发生的工作的实际内容 - 我假设您选择忽略的代码部分为了简单起见)做任何UI绑定的工作。如果确实如此,那你就不幸了,使用Application.DoEvents()
是最好的选择。
但是,如果没有,并且您对异步代码有足够的控制权,那么您可以做的不是尝试从任务中调用UI ,而是传递{{1将工作描述回UI线程(作为Action
的{{1}}),然后在那里处理它的调用。
请注意,我已经简化了Task
的实现,因为它不再从非UI线程调用。
警告:简化的代码,不适合生产。
Result