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 スレッド自体で単純に作業を行う方がはるかに理にかなっています。あなたが提供したコードでは、2 つのスレッドが同時に処理を効果的に実行することはないため、1 つのスレッドに勝るものはありません。

于 2012-08-29T15:19:18.113 に答える