对Windows窗体进行线程安全调用会冻结应用程序

时间:2011-12-22 15:10:15

标签: c# .net visual-studio-2008

我的应用程序中有一个异常处理项目,可以从任何地方调用,以向用户显示系统出现问题。当按照预期在UI中的某个地方进行调用时,一切都很有效。当我从应用程序的任何UI部分进行调用时,一切都冻结了。我将代码包装在线程安全调用中,当单步调试时,它们不需要调用Invoke。任何帮助是极大的赞赏。代码如下:

表格内

    void err_DispEvent(string text)
    {
        if (InvokeRequired)
        {
            Invoke(new Error.DisplayDelegate(err_DispEvent), new object [] {text});
        }
        else
        {
            this.Show();
        }        
    }

来自班级的电话

public void FaultError(string errorMsg)
    {
        FaultForm fform = new FaultForm(errorMsg, "Internal Fault");
        if (this.dispEvent != null)
        {
            dispEvent(errorMsg);
        }
    }

    public event DisplayDelegate DispEvent
    {
        add { dispEvent += value; }
        remove { dispEvent -= value; }
    }

    private event DisplayDelegate dispEvent;

    public delegate void DisplayDelegate(string text);

在应用程序中如何使用类的示例

ECDUExceptions.Error newError = ECDUExceptions.Error.getInstance();
newError.FaultError("Heater is not responding to function calls, it has been turned off");

3 个答案:

答案 0 :(得分:2)

重新调用方法时的一些信息:

  1. 使用BeginInvoke(...)代替Invoke(...),因为这不会等待调用完成,因此不会冻结调用线程。

  2. 重新调用时使用Action。因此,在您的情况下,您可以将调用更改为:

    BeginInvoke(new Action<string>(err_DispEvent), text);
    

答案 1 :(得分:1)

使用BeginInvoke(...)代替Invoke(...)。这会将您的消息请求放在队列的末尾

答案 2 :(得分:0)

为应显示的消息创建某种队列。

从您需要的任何线程填充队列。

从负责显示消息的GUI中,使用计时器出列并显示它们。

简单但会毫不费力地工作。而且你不需要Invoke()任何东西,因为Forms.Timer在UI消息循环上运行。