2012-08-01 83 views
4

剧情简介:我在做什么线程错误?

我试图将非线程应用程序转换为线程应用程序。我在大约10年的时间里没有在应用程序中使用线程,并且对这个概念非常生疏。这只是我没有抓住的东西。你能看看我的(很短的)代码之前和之后,看看我做错了什么,为什么它是错的?所有帮助非常感谢!谢谢!

错误看出:

我的代码没有响应。我可以运行并执行这些按钮来启动应用程序,但不会启动一个新线程而只是工作,它们会冻结并显示“无响应”消息。我不确定我做错了什么。我是否错误地实现了线程?

非线程代码:

//this opens the user input windows form 
private void UserInputButton_Click(object sender, EventArgs e) 
{ 
    enumerationStation EnumerationForm = new enumerationStation(); 
    EnumerationForm.Show(); 
    //userform UserForm = new userform(); 
    //UserForm.Show(); 
} 

//this opens the correlationApplication windows form 
private void CorrelationApplication_Click(object sender, EventArgs e) 
{ 
    CorrelationApplication CorrelationApplicationForm = new CorrelationApplication(); 
    CorrelationApplicationForm.Show(); 
} 

破碎线程代码:

//this opens the user input windows form 
private void UserInputButton_Click(object sender, EventArgs e) 
{ 
    BackgroundWorker bg = new BackgroundWorker(); 
    bg.DoWork += new DoWorkEventHandler(enumerationStuff); 
    bg.RunWorkerAsync(); 

} 
//run enumeration application in new thread 
private void enumerationStuff(object sender, DoWorkEventArgs e) 
{ 
    enumerationStation EnumerationForm = new enumerationStation(); 
    EnumerationForm.Show(); 
} 

//this opens the correlationApplication windows form 
private void CorrelationApplication_Click(object sender, EventArgs e) 
{ 
    BackgroundWorker bg = new BackgroundWorker(); 
    bg.DoWork += new DoWorkEventHandler(correlationStuff); 
    bg.RunWorkerAsync(); 
} 
//run correlation application in new thread 
private void correlationStuff(object sender, DoWorkEventArgs e) 
{ 
    CorrelationApplication CorrelationApplicationForm = new CorrelationApplication(); 
    CorrelationApplicationForm.Show(); 
} 
+3

简单的回答:不要这样做。使用线程进行昂贵的计算。使用TPL。 – SLaks 2012-08-01 13:10:40

+3

我敢肯定,从UI线程中打开新的UI形式是一个坏主意。 – asawyer 2012-08-01 13:12:38

+0

另外,好像你是从backgroundworker调用UI方法:'EnumerationForm.Show();'。这应该会为您弹出一个例外。您应该只在主线程上使用UI方法,并使用其他线程来完成与其他线程无关的其他任务。 – devundef 2012-08-01 13:13:52

回答

4

BackgroundWorkers是专为正是这样做的 - 在后台运行。它们不是为了显示新窗口或自己展示任何UI而设计的 - 根据定义,它是前台工作。 BackgroundWorkers不处理任何消息,因此它们不会响应鼠标点击,键盘输入或任何事情,这就是为什么窗口只显示“不响应”的原因。

很难回答这个问题,因为我并不十分清楚你在这里实际实现的目标。你的第一个非线程代码有什么问题?

如果“单个应用程序”(实际上只是表单)冻结整个应用程序,它们可能在UI线程中做了很多工作。在这种情况下,BackgroundWorkers可能是一个解决方案,但是你在错误的地方使用它们。找到正在做“很多工作”的代码(无论是哪种工作),并查看是否可以将该代码(仅限该代码)放入BackgroundWorker中。然而,你不能做的是在BackgroundWorker内部对UI做任何事情 - 你只有一个UI线程(你开始的那个线程),只有那个线程可以触及UI。

+0

我没有意识到这一点。我已经阅读了几个小时的后台工作人员文档,并且从未发生过我:)这可能是我的问题 – toosweetnitemare 2012-08-01 13:25:47

2

.NET/Windows用户界面不允许从任何用户界面线程执行任何 UI操作。简而言之,UI本身是单线程的,而任何不接触UI的长时间运行的操作可以愉快地发生在辅助/后台线程中。

这就是为什么像Control.Invoke这样的东西存在,以便您可以请求在UI线程上下文中执行一段特定的代码。

+0

如何使control.invoke适用于这种情况?这听起来像我想要做的。 – toosweetnitemare 2012-08-01 13:24:45

+1

@toosweetnitemare这就是你想要做的,但这不是你应该做的。你可以使用'Control.Invoke'从后台线程更新* UI,而不是用它来接受输入等等。这种事情必须在UI线程上完成。 – James 2012-08-01 13:30:03

+1

@toosweetnitemare:尽管pete说的是正确的,但仍坚持Chris在他上面的评论中指出的方法。除此之外:BackgroundWorker有一个ReportProgress事件,它允许您用工作线程中的信息更新UI,而不会崩溃任何东西。但是,这仍然只有克里斯或詹姆斯指出的情景才有意义。 – 2012-08-01 13:36:40

2

这里的主要问题是您试图在后台线程上创建&运行GUI组件。鉴于你需要提示用户输入,我不明白你为什么想要将这些代码编入单独的线程。

保持您的表单在UI线程中启动,然后将这些表单执行的任何额外工作传递到后台线程中。