InvokeRequired=true,但BeginInvoke失败导致冻结



C#windows窗体VS 2013 OS:Win7

我遇到了一个有趣的问题,invokeRequired为true,但当我调用beginInvoke()时,它从不执行,窗口也从不关闭。

然而,当我完全删除beingInvoke()时,窗口会正常关闭

     public void CloseMyForm()
            {
//if I remove this if block altogether including beingInvoke() the window closes ok
                if ( !this.IsDisposed && this.InvokeRequired && this.IsHandleCreated )
                {
                    log("callin begininvoke()"); //this is logged correctly 
                    this.BeginInvoke((MethodInvoker)delegate() { CloseMyForm(); });
                    return;
                }
               log("outside of begin invoke"); //this is never logged
               this.Close();
            }

CloseMyForm由一个单独的线程调用,该线程在启动时是这样创建的。请注意,这不是主窗口,而是从主窗体打开的单独窗口。

Thread connectThread = new Thread(new ThreadStart(CheckWhenToCloseMyForm)); 
    public void CheckWhenToCloseMyForm()
    {
        while (true)
        {
            CallSomeFunc();
            CallSomeFunc1();
            if (allconditionsmet)
            {
                System.Threading.Thread.Sleep(1000);
                CloseMyForm();
break;
            }        
        }       
    }

BeginInvoke通过基本Control类可用。

在上创建控件的基础句柄的线程上异步执行委托

如果InvokedRequired属性实际上为true,则意味着"调用方在对控件进行方法调用时必须调用invoke方法,因为调用方所在的线程与创建控件的线程不同"。

您似乎错误地调用了BeginInvoke,您应该尝试调用Invoke

在拥有控件的底层窗口句柄的线程上执行指定的委托

public void CloseMyForm()
{
    if (!this.IsDisposed && this.InvokeRequired && this.IsHandleCreated)
    {
        log("calling invoke()");
        this.Invoke((MethodInvoker)delegate() { CloseMyForm(); });
    }
    else
    {
        log("outside of invoke"); // this is never logged
        this.Close();
    }
}

看看这个巧妙的小扩展方法,它可以帮助简化这个过程。有了这个,你可以这样写你的关闭方法。

public void CloseMyForm()
{
    this.ThreadSafeInvoke(() => this.Close());
}

好吧,既然您已经提供了这个片段,我就理解了这个问题。

Thread connectThread = new Thread(new ThreadStart(CheckWhenToCloseMyForm)); 
public void CheckWhenToCloseMyForm()
{
    while (true)
    {
        CallSomeFunc();
        CallSomeFunc1();
        if (allconditionsmet)
        {
            System.Threading.Thread.Sleep(1000);
            CloseMyForm()
        }        
    }       
}

while循环中,您需要在调用CloseMyForm之后调用breakreturn。就是这样…非常简单。您可以使用BeginInvokeInvoke

最新更新