• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 609
  • Last Modified:

C# 2010: Threading, Delegates -- Form 'locking up' when trying to Show form!

Hello,

I am using C#.NET 2010, but I'm having an issue.  I have tried to simplify the coding into a basic application that does it.

What's happening is I have a thread, and then I try to show another form within that thread when certain objectives have been met (isClicked == true).. The problem is, when the form tries to display Form2, Form2 is in a locked up state where I can't move the window. I've attached the basic coding, you'll need a simple Form1 and Form2 as well.

I believe I need something called 'Delegates', but I am not sure how to use it, and I fully don't understand it so far and how it works. The goal is to simply display Form2 with no freezes while being run in the thread.

Any suggestions or tips?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    static class Program
    {
        public static Form2 m_ChildForm;
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

Open in new window

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private Thread Messages;
        private bool isConnected;
        private bool isClicked = false;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Program.m_ChildForm = new Form2();
            isConnected = true;
            Messages = new Thread(new ThreadStart(this.Communication));
            Messages.Start();
        }

        private void Communication()
        {
            while (isConnected == true)
            {
                if (isClicked == true)
                {
                    Program.m_ChildForm.Show();
                    isClicked = false;
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            isClicked = true;
        }
    }
}

Open in new window

0
Valleriani
Asked:
Valleriani
  • 4
  • 3
2 Solutions
 
Carlos VillegasFull Stack .NET DeveloperCommented:
Hello, you specific problem is this:
private void Communication()
{
    while (isConnected == true)
    {
        if (isClicked == true)
        {
            Program.m_ChildForm.Show();
            isClicked = false;
        }
    }
}

Open in new window

This loop dont let the windows messages be processed, so you can do this to allow the messages queue be processed:
private void Communication()
{
    while (isConnected == true)
    {
        if (isClicked == true)
        {
            Program.m_ChildForm.Show();
            isClicked = false;
        }
        Application.DoEvents();
    }
}

But you need to check your design, for what you want  to use that loop?
0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
And sorry for my poor english...
0
 
VallerianiAuthor Commented:
Overall whats happening is i'm waiting for the client to connect and get a OK message, when it gets a OK, it will show the form.  Communication() was meant to be hooked up with sockets, and processes messages received from the server.
0
Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

 
VallerianiAuthor Commented:
Hrm that doesn't work either unless I'm always running DoEvents, so something seems to be not working yet.

If Doevents is called, it loads but then it locks up again unless I keep calling DoEvents
0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
Yes, but that is not the correct way, I will give you an example....
0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
Hi, ok, I did this small project that have the behaviour that you want by using events:
http://dl.dropbox.com/u/13237304/MyNewApplication.zip

Try it.
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
You need to show the "child form" from the main UI thread.

*Haven't looked at the code in yv989c's ZIP file...

Here's one way:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

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

        private Thread Messages;
        private bool isConnected;
        private bool isClicked = false;

        private void Form1_Load(object sender, EventArgs e)
        {
            Program.m_ChildForm = new Form2();
            isConnected = true;
            Messages = new Thread(new ThreadStart(this.Communication));
            Messages.IsBackground = true;
            Messages.Start();
        }

        private void Communication()
        {
            while (isConnected == true)
            {
                if (isClicked == true)
                {
                    ShowChildForm();
                    isClicked = false;
                }
            }
        }

        private void ShowChildForm()
        {
            if (this.InvokeRequired)
            {
                this.Invoke((MethodInvoker)(delegate() { ShowChildForm(); }));
            }
            else
            {
                if (Program.m_ChildForm == null || Program.m_ChildForm.IsDisposed)
                {
                    Program.m_ChildForm = new Form2();
                }
                Program.m_ChildForm.Show();
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            isClicked = true;
        }

    }
}

Open in new window

0
 
VallerianiAuthor Commented:
Both solutions worked but I found the work from Idle_Mind was a bit better in the end as it didn't require much editing of my current coding. when I used ShowDialog(), it did load the form, but it didn't display anything as it should. Using:

        public void ShowChildForm()
        {
            if (this.InvokeRequired)
            {
                this.Invoke((MethodInvoker)(delegate() { ShowChildForm(); }));
            }
            else
            {
                if (Program.m_ChildForm == null || Program.m_ChildForm.IsDisposed)
                {
                    Program.m_ChildForm = new MainChat(this);
                }
                Program.m_ChildForm.Show();
            }
        }

I was able to use the global m_ChildForm in all locations, including in the thread.

Though both did work in there examples though, in my actual coding it was Idle_Minds' coding who seemed to handle my full current source with minimal changes.

Thanks both!
0

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now