Ashley
Ashley

Reputation: 81

Thread safe calls to windows form are freezing the application

I have an Exception Handling project in my application that can be called from anywhere to show the user there is a problem with with system. Everything works great when the call is made from somewhere in the UI as expected. When I make calls from no UI parts of the application everything freezes. I have the code wrapped in the thread safe calls and when stepping through they don't require the Invoke call. Any help is greatly appreciated. Code below:

Inside the form

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

Call from the class

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);

Sample of how the class is used in the application

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

Upvotes: 0

Views: 720

Answers (3)

Samuel Slade
Samuel Slade

Reputation: 8623

Some information when re-invoking methods:

  1. Use BeginInvoke(...) instead of Invoke(...) as this will not wait for the call to finish, and so won't freeze the calling thread.

  2. Use an Action when re-invoking. So in your case, you could change your invocation to:

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

Upvotes: 2

Daniel Mošmondor
Daniel Mošmondor

Reputation: 19976

Create a queue of some sort for the messages that should be displayed.

Fill the queue from whatever thread you required.

From the GUI responsible for showing the messages, use timer to dequeue and show them.

Simplistic but will work effortlessly. And you won't need to Invoke() anything since Forms.Timer runs on UI message loop.

Upvotes: 0

Elastep
Elastep

Reputation: 3408

Use BeginInvoke(...) instead of Invoke(...). THis will put your message request in the end of the queue

Upvotes: 1

Related Questions