使用构造函数启动新线程

时间:2012-03-14 12:58:22

标签: c# multithreading user-interface

我完成了我的小项目,做了一些繁重的工作。我意识到在这个短暂的计算时间内,我的GUI冻结了。所以我做了一些研究,发现这个=> http://www.codeproject.com/Articles/4381/Threading-out-tasks-in-a-C-NET-GUI

我开始实现这是我的项目,但我意识到这个特定的实现在我的项目中不起作用。

在我的项目中,我有许多类和一个“管理器”来控制所有其他类。如果我初始化这个Manager类,它已经在构造函数中完成了繁重的工作。

致我的问题:

如何使用构造函数启动新线程?

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


            }
        }

编辑: 好吧,我决定重新编码我的程序。现在繁重的工作在一个功能,但我认为我犯了一个错误。

整个程序看起来像这样:

 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

            }
        }

sl.Invoke(new MethodInvoker(mgr.test)); // first try有效但它仍然会冻结我的GUI。

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

这条线没有任何作用。

我的测试功能:

 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 个答案:

答案 0 :(得分:3)

您应该使用不同的方法。您的构造函数仍在GUI线程上调用。

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

答案 1 :(得分:2)

将“重吊”从构造函数移到某种“worker”并在线程中运行该方法。

从以下位置更改管理员:

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

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

public void DoWork()
{
    //heavy lifting
}

和调用

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

注意:如果您访问/更改线程中的UI元素,请不要忘记调用该调用!

答案 2 :(得分:1)

嗯,你可以使用:

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

...但是你不会在其他代码中引用经理。

老实说,无论如何,由于各种原因,在构造函数中进行繁重的工作通常是个坏主意。将这项工作转移到其他地方会更好:

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