2011-12-22 82 views
0

我的应用程序中有一个异常处理项目,可以从任何地方调用以显示用户系统有问题。按照预期从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"); 

回答

2

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

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

  2. 重新调用时使用Action。所以你的情况,你可以在你的调用更改为:

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

如果签名匹配,是不是'BeginInvoke(err_DispEvent,text);'足够? – Adam 2011-12-22 15:17:02

+0

@codesparkle我相信是这样的,我写了很多更清晰的内容。 – 2011-12-22 15:25:37

+0

你会介意,如果我建议编辑你的问题(显示两种选择)? – Adam 2011-12-22 15:26:25

1

使用的BeginInvoke(使用.. )而不是Invoke(...)。这将把您的消息请求放在队列末尾

0

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

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

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

简单但不费吹灰之力。你不需要调用()任何东西,因为Forms.Timer在UI消息循环上运行。

+0

这样的队列已经存在:消息循环。 使用BeginInvoke()在队列末尾添加一个动作。 – Daniel 2011-12-22 15:46:44