我的程序中有以下子目录:
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
运行此程序挂起。有没有人有这个问题的解决方案。 我是线程新手。
答案 0 :(得分: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线程本身上进行工作而不是开始新工作就更有意义了。在你提供的代码中,没有两个线程可以同时有效地进行处理,所以它并不比单个线程好。