使用构造函数启动新线程
本文关键字:线程 新线程 构造函数 启动 | 更新日期: 2023-09-27 18:27:50
我完成了我的小项目,做了一些繁重的工作。我意识到在这么短的计算时间内,我的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
}
}
CCD_ 1工作,但它仍然冻结了我的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();
}
对此应该使用不同的方法。您的构造函数仍在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();
}));
}
}
将构造函数中的"重载"移到某种"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元素,不要忘记调用Invoke!
好吧,可以使用:
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);