user5505472
user5505472

Reputation:

How to abort thread invoked ShowDialog

Have C# Windows Forms application with secondary thread that receives requests from an external system to show or hide a form/dialog. I understand that secondary threads do not have a message loop mechanism. I understand that ShowDialog has its own message loop, thus a secondary thread can invoke it, but the secondary thread is then blocked until the form closes, and thus cannot respond to later requests to hide the form. The problem is, how to get the form displayed by the secondary thread to hide [or again become visible]. Tried invoking Interrupt on secondary thread, but that does not interrupt or abort the ShowDialog. Nothing appears to abort ShowDialog except a ShowDialog UI callback that calls Close.

Upvotes: 1

Views: 848

Answers (1)

MrApnea
MrApnea

Reputation: 1946

Actually both forms share the same message loop.

Every code that handles gui must be ran on the same thread (which handles the gui part). What you need is to run the commands on that thread using BeginInvoke.

I made a sample application which only has a simple button and when you press it a thread is started which sleeps 3 seconds and then opens the dialog and sleeps again and next time it closes it down and so forth.

Here is the code for the main window:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    Thread t;
    Form2 f2;

    private void button1_Click(object sender, EventArgs e)
    {
        t = new Thread(ThreadMethod);
        t.Start();
        button1.Enabled = false;
    }

    private void ShowForm()
    {
        f2 = new Form2();
        f2.ShowDialog();
    }

    private void ThreadMethod()
    {
        for (; ; )
        {
            Thread.Sleep(3000);
            if(f2 == null)
            {
                BeginInvoke((Action)(() => { ShowForm(); }));
            }
            else
            {
                f2.CloseMe();
                f2 = null;
            }
        }
    }
}

And then the code for the form used as a dialog:

using System;
using System.Windows.Forms;

namespace QuestionTesting
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        public void CloseMe()
        {
            BeginInvoke((Action)(() => { Close(); }));
        }
    }
}

This is just simple code and adapt it as you see fit. Instead of the one liners you can create a delegate instead and use that in the BeginInvoke call.

Upvotes: 1

Related Questions