bugfixr
bugfixr

Reputation: 8077

Displaying a form locks up mono

I've got a mono app written in c# and executed on a Mac using "mono myapp.exe"

The app itself is a "Windows Application" when viewed from the project properties, but it doesn't always show a window. In program.cs, there is a static Main:

static void Main(string[] args) {
    UserClient client = new UserClient();
    client.Start(args);
}

public class UserClient {
    public void Start(string[] args) {
          // Talk to server, listen for instructions, etc.
          ....
          // Launch the "Stay Alive" thread
          // Just a thread that Sleeps/Loops watching for an exit command; mainly used to keep the process alive
    }
}

Inside the UserClient's Start method, there is a piece of code that continuously monitors a server which gives it instructions to do things. One of the things it does is optionally displays a message using a windows form.

When the server instructs the process to display a message, it instantiates a form, displays it using frm.ShowDialog() and then after 30 seconds, a timer on the form runs Close() and the frm then gets disposed. However, when this happens, on my Mac I see an application title bar saying "mono" and a new icon on my dock bar for the mono app. After about 2 minutes the mono process in Activity Monitor shows "Not Responding." This eventually will prevent the user from logging out, shutting down, etc. (because Mac OS can't kill mono gracefully).

ON THE OTHER HAND... if the server never tells the process to display that form, everything runs fine and dandy: a dock icon never shows up (which is good!), mono title bar never shows up and the mono process continues to run happily, not preventing the system from shutting down or rebooting.

Anyone experienced this or have ideas on what's causing it? My guess is that it's a new GUI thread being created by the form which isn't ever being shutdown and is somehow causing a lockup, though I'm unsure of how to handle it.

Thanks for any suggestions.

Update:

Here's some code to easily reproduce and see this happening. I realize that this seems kind of "non-standard." Having said that, the below works perfectly in a Windows environment and provides the desired result of not showing an icon in the task area except when showing a message. Currently, using Application.Run and simply doing frm.ShowDialog() produce exactly the same result.

In the end what we need is to be able to display the form, then destroy the form and any associated icon from the dock. I suspect the GUI is starting a thread which isn't ever being disposed, which is why the dock icon remains. Is there a way to make sure the GUI thread is taken care of?

static class Program {
    static void Main() {            
        StartupClass s = new StartupClass();
        s.start();
    }
}

public class StartupClass {
    Thread stayAliveThread;

    public void start() {
        // Stay alive thread
        stayAliveThread = new Thread(stayAliveLoop);
        stayAliveThread.Start();

        // This shows a form and would normally be used to display temporary and brief messages to the user. Close the message and you'll see the undesired functionality. 
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
        Application.Exit();
        Application.ExitThread();
    }

    /// <summary>
    /// Keep the app alive.
    /// </summary>
    private void stayAliveLoop() {
        while (true) {
            Thread.Sleep(10000);
            // In the real project this method monitors the server and performs other tasks, only sometimes displaying a message.
        }
    }
}

Upvotes: 2

Views: 1118

Answers (3)

bugfixr
bugfixr

Reputation: 8077

In the end, I couldn't resolve this. I created a process that launched another app which displayed the message form. Not really a true answer, but the solution I had to go with.

Upvotes: 0

konrad.kruczynski
konrad.kruczynski

Reputation: 47641

I can't see anything like initializing message loop for windowed application. I.e. in windows forms case something like Application.Run(). If you do not have it, no wonder application freezes. In any case, posting more code could be helpful, as stated in comment.

Upvotes: 1

sehe
sehe

Reputation: 393583

I feel I'm missing several things. Most notably

 [STAThread]
 static void Main(string[] args) { //....

Also see this answer: Windows Forms and ShowDialog problem

Upvotes: 1

Related Questions