Starting a new thread using the constructor

I finished my little project that makes the hard climb. I realized that in this short computation time my GUI freezes up. So I did some research and I found this => http://www.codeproject.com/Articles/4381/Threading-out-tasks-in-aC-NET-GUI

I started to implement this in my project, but I realized that this particular implementation was not working in my project.

In my project I have many classes and one "manager" that controls all the other classes. If I initialize this Manager class, it already does the heavy lifting in the constructor.

To my question:

How to start a new thread using a countermeasure?

private void fileWatcher_Changed(object sender, System.IO.FileSystemEventArgs e)
        {


            if (System.IO.File.Exists(e.FullPath) == true)
            {

                Manager mgr = new Manager(e, handreader); // here starts the heavy lifting
                Thread mgrThread = new Thread(new ThreadStart(mgr));  // what to do ?
                sl.Text = mgr.test();
                txtLog.Text = mgr.output();


            }
        }

      

EDIT: ok, I decided to recode my program. now a heavy lift in one function, but I think I made a mistake.

the whole program looks like this:

 private void fileWatcher_Changed(object sender, System.IO.FileSystemEventArgs e)
        {


            if (System.IO.File.Exists(e.FullPath) == true)
            {
                Manager mgr = new Manager(e, handreader, txtLog, sl);
                //sl.Invoke(new MethodInvoker(mgr.test));
                sl.Invoke(new MethodInvoker(mgr.test)); // first try 
                Thread mgrThread = new Thread(new ThreadStart(mgr.test)); // second try

            }
        }

      

works sl.Invoke(new MethodInvoker(mgr.test)); // first try

, but it still hangs on my GUI.

Thread mgrThread = new Thread(new ThreadStart(mgr.test)); // second try

      

and this line does nothing.

my test function:

 public void test()
    {
        StringBuilder builder = new StringBuilder();
        foreach (PlayerController pc in fm.lPc)
        {
          Range  range = new Range(handReader.hand, handReader.handversus, pc);
          builder.Append(pc.getHeroCardsSimple()+" vs 100% range =   "+range.vsRange()+"\r\n");
        }
        sl.Text = builder.ToString();
    }

      

+3


source to share


3 answers


To do this, you must take a different approach. Your constructor is still called on the GUI thread.



    Func<Manager> asyncConstructor;
    private void fileSystemWatcher1_Changed(object sender, System.IO.FileSystemEventArgs e)
    {
        asyncConstructor = new Func<Manager>(() => new Manager());

        asyncConstructor.BeginInvoke(ManagerConstructed, null);
    }

    private void ManagerConstructed(IAsyncResult result)
    {
        Manager mgr = asyncConstructor.EndInvoke(result);
        //we can only access form controls from the GUI thread, 
        //if we are not on the gui thread then
        //do the changes on the gui thread.
        if (this.InvokeRequired)
        {
            this.Invoke(new Action(() =>
            {
                sl.Text = mgr.test();
                txtLog.Text = mgr.output();
            }));
        }
    }

      

+3


source


Move the "heavy lift" from the constructor to some "worker" and run that method on a thread.

Change the dispatcher:

public Manager(/*params*/)
{
    //params
    //heavy lifting
}

      

to



public Manager(/*params*/)
{
    //params
}

public void DoWork()
{
    //heavy lifting
}

      

and call

Manager mgr = new Manager(e, handreader);
Thread mgrThread = new Thread(new ThreadStart(mgr.DoWork));
mgrThread.Start();

      

WARNING: If you are accessing / modifying UI elements on the thread, remember to make calls!

+2


source


Well, you could use:

Thread mgrThread = new Thread(() => new Manager(e, handreader));

      

... but then you won't have a manager reference for the rest of your code.

To be honest, doing heavy lifting in a constructor is usually a bad idea for a variety of reasons. It would be better to move this work elsewhere:

// Constructor just sets things up
Manager mgr = new Manager(e, handreader);
// DoWork method does the real work
Thread mgrThread = new Thread(mgr.DoWork);

      

+1


source







All Articles