2012-03-14 4 views
3

Я закончил свой маленький проект, который делает тяжелый подъем. я понял, что в это короткое время вычисления мой графический интерфейс замерзает. Поэтому я провел некоторое исследование, и я нашел это =>http://www.codeproject.com/Articles/4381/Threading-out-tasks-in-a-C-NET-GUIЗапуск новой темы с помощью конструктора

Я начал реализовывать это мой проект, но я понял, что эта конкретная реализация не работает в моем проекте.

В моем проекте у меня есть много классов и один «менеджер», который контролирует все остальные классы. Если я инициализирую этот класс Менеджера, он уже делает тяжелый подъем в конструкторе.

На моем вопросе:

Как я начать новую тему с застройщиками?

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

вся программа выглядит следующим образом:

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

Для этого вам следует использовать другой подход. Ваш конструктор все еще вызывается в потоке графического интерфейса.

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

Даже если это отвечает на главный вопрос, я согласен с Джоном: не делайте тяжелую работу в конструкторе! – ChrFin

+0

Да, конечно, но это другой вопрос – Bas

2

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

Изменение менеджер из:

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

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

+0

пытался реализовать ваши рекомендации, но без успеха –

+0

Только что проверил правку: Вы забыли, чтобы начать нить! См. Мое редактирование ... – ChrFin

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); 
Смежные вопросы