0

我的程序中有以下子程序:

public sub RunThis()
Me.Hide()
NEWFORM.Show()
Dim t = New Thread(Sub() Me.printToPowerPoint(saveLocation, printlist))
t.SetApartmentState(ApartmentState.STA)
t.IsBackground = True
t.Start()
While t.isAlive

end while
NEWFORM.close()
Me.Close()
end sub

运行这个我的程序挂起。有没有人有这个问题的解决方案。我是线程新手。

4

1 回答 1

2

您可能知道,在 WinForm 项目中,UI 只能从单个线程处理。这被亲切地称为 UI 线程。这就是为什么在任何时候需要访问或修改 UI 元素时,都必须调用控件或表单的Invoke方法。该Invoke方法使给定的委托在 UI 线程上运行。但是,这样做不会中断 UI 线程已经在执行的任何处理。如果 UI 线程当前很忙,当你调用 时Invoke,它会挂起,直到 UI 线程不再忙,然后它会执行给定的委托。

因此,在您的代码中,您正在启动一个新线程,该线程内部试图在 UI 线程上调用一个方法。但是,在启动新线程后,您会立即进入一个循环,使 UI 线程保持忙碌,直到另一个线程完成。因此,当您的新线程调用回 UI 线程时,UI 线程很忙,并且两个线程实际上都会永远挂起。

DoEvents是一个关键字,您可以从 UI 线程中的冗长进程或循环中调用,以表明您想要暂停当前处理,从而释放 UI 线程来处理任何等待的窗口消息(绘制事件、单击事件、调用请求等)。一旦处理了所有这些待处理的窗口消息,它将返回执行您调用后的下一条语句DoEvents。因此,如果DoEvents在循环内调用使其正常工作,这意味着您的新线程必须调用回 UI 线程,或者在继续之前等待处理其他一些窗口消息。

打电话DoEvents是危险的,并且被广泛认为是不好的做法。通常,如果您需要调用DoEvents,这表明您需要重新考虑您的设计。通常有更好的方法来做你正在做的事情。

在您的情况下,似乎启动新线程完全没有意义。除非您已缩写代码,否则似乎只要您启动新线程,您只需将 UI 线程置于等待其他线程完成即可。如果是这种情况,那么简单地在 UI 线程本身上完成工作而不是开始一个新线程会更有意义。在您提供的代码中,没有两个线程将同时有效地进行处理,因此它并不比单个线程好。

于 2012-08-29T15:19:18.113 回答