我在 Windows窗体上有下一个代码:
if (control.IsHandleCreated)
{
if (control.InvokeRequired)
{
control.BeginInvoke(action);
}
else
{
action.Invoke();
}
}
调试,它进入InvokeRequired = false
并且它完美运行,但在生产环境中。它以某种方式进入InvokeRequired = true
,因此它应该执行BeginInvoke()
方法。
没有。它永远不会进入行动。此脚本属于 DataGrid 控件,但在同一表单上的不同 DataGrids , Comboboxes 等上具有相同的功能;所以它似乎是这个 DataGrid 特有的东西。 有什么想法吗?
由于
答案 0 :(得分:1)
我试图找到真正的答案,我的猜测是,当您调用begininvoke时,一条消息被放入该线程的队列中。该线程将项目从此队列中取出,并按1对其进行处理。比方说,您调用BeginInvoke的速度快于处理线程可以处理的速度...您的队列将变得越来越大,并且需要越来越多的时间来处理。那么主线程可能在执行其他操作时被阻塞。当您的线程正在执行其他操作时,它将不会处理队列外的项目,因此线程无法访问控件。 我测试了您的代码,如果缺少访问权限,则代码无法重复,然后我更改了代码,并在重复一两次后可以正常工作:
int i = 0;
public delegate void AsyncMethodCaller();
private void proc2()
{
Action action = () => control1.Text = (i += 1).ToString();
if (control1.IsHandleCreated)
{
if (control1.InvokeRequired)
{
control1.BeginInvoke(new AsyncMethodCaller(proc2));
}
else
{
action.Invoke();
}
}
else
{
MessageBox.Show("Handle creation error");
}
}
private void proc1()
{
for (int i=0; i<1000; i++)
{
//do something
}
}
private void button1_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(proc1);
thread1.Start();
Thread thread2 = new Thread(proc2);
thread2.Start();
}
答案 1 :(得分:0)
您必须使用以下内容:
public static void action()
{
if (varControl.InvokeRequired)
{
//Seems following code is better than BeginInvoke().
varControl.Invoke(new MethodInvoker(() => action()));
}
else
{
//your code
}
}
我喜欢以下不需要委托的代码,并且仅在需要调用时才使用invoke:
MethodInvoker invoker =new MethodInvoker (action);
if (varControl.InvokeRequired)
{
varControl.Invoke(invoker);
//I think that Invoke() is better than BeginInvoke()
}
else
{
invoker.Invoke();
//SomeTimes BeginInvoke() not works correctly,
//and you have to use Invoke().
}
答案 2 :(得分:0)
这就是我刚刚使用的:
<your control>.Invoke(new MethodInvoker(delegate () {
… do your work here
}));
-吉娜