Начиная новую тему с конструктором - PullRequest
3 голосов
/ 14 марта 2012

Я закончил свой маленький проект, который делает тяжелую работу. я понял, что за это короткое время расчета мой графический интерфейс зависает. Итак, я провел небольшое исследование и нашел это => 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 работает, но все равно замораживает мой графический интерфейс.

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 ]

3 голосов
/ 14 марта 2012

Вы должны использовать другой подход для этого. Ваш конструктор все еще вызывается в потоке 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();
            }));
        }
    }
2 голосов
/ 14 марта 2012

Переместите «тяжелую работу» из конструктора в некую «рабочую» и запустите этот метод в потоке.

Измените Диспетчер с:

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

ВНИМАНИЕ: Если вы получаете доступ / изменяете элементы пользовательского интерфейса в потоке, не забывайте вызывать эти вызовы!

1 голос
/ 14 марта 2012

Ну, вы могли бы использовать:

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