我有一个表单,其作用是向用户显示循环进度图形,同时用户正在等待特定的事情要完成。这是它的简单代码:
Public Class FrmCircularProgress
Sub New(progressType As DevComponents.DotNetBar.eCircularProgressType)
InitializeComponent()
CircularProgress1.ProgressBarType = progressType
StartCircular()
End Sub
Public Sub StartCircular()
Me.CircularProgress1.IsRunning = True
End Sub
Public Sub StopCircular()
Me.CircularProgress1.IsRunning = False
End Sub
End Class
以下是我如何使用它的例子(在这种情况下是两个地方)
Dim createArticle As New Artikel
'http://stackoverflow.com/questions/33030706/put-long-running-method-into-task-showing-new-form-meantime-and-closing-it-once
Dim pic As New FrmCircularProgress(eCircularProgressType.Donut)
Dim tsk As Task(Of Boolean) = Task.Factory.StartNew(Of Boolean)(Function()
'--Run lenghty task
Dim resu = False
Try
resu = createArticle.ProcessArticle(_artikelsAndTheirVariationsFinal)
'--Close form once done (on GUI thread)
Catch sqlex As Exception
pic.Invoke(Sub() MessageBox.Show(pic, sqlex.Message))
' pic.Invoke(Sub() MessageBox.Show(pic, ex.Message))
'pic.Invoke(Sub() TaskDialog.Show(pic, New TaskDialogInfo("Information", eTaskDialogIcon.BlueStop, "WizardPageDescriptionUberblick_BeforePageDisplayed", ex.ToString, eTaskDialogButton.Ok, eTaskDialogBackgroundColor.Blue, Nothing, Nothing, Nothing, "Jakis footer text", Nothing)))
Finally
End Try
pic.Invoke(New Action(Sub() pic.StopCircular()))
pic.Invoke(New Action(Sub() pic.Close()))
Return resu
End Function)
'--Show the form
pic.ShowDialog()
Task.WaitAll(tsk)
If tsk.Result = True Then
TaskDialog.Show(New TaskDialogInfo("Information", eTaskDialogIcon.BlueStop, "Infor", "New articel and every data has been added correctly", eTaskDialogButton.Ok, eTaskDialogBackgroundColor.Blue, Nothing, Nothing, Nothing, "Jakis footer text", Nothing))
'http://stackoverflow.com/questions/33030706/put-long-running-method-into-task-showing-new-form-meantime-and-closing-it-once
pic = New FrmCircularProgress(eCircularProgressType.Line)
Dim work As Task = Task.Factory.StartNew(Sub()
'--Run lenghty task
PrepareUberblick()
'--Close form once done (on GUI thread)
pic.Invoke(New Action(Sub() pic.StopCircular()))
pic.Invoke(New Action(Sub() pic.Close()))
End Sub)
'--Show the form
pic.ShowDialog()
Task.WaitAll(work)
If WYSWIG_Uberblick.Document IsNot Nothing Then
WYSWIG_Uberblick.Document.Write(String.Empty)
End If
'--Pobranie wszystkich html'ow wszystkich podsekcji artykulow (w tym wypadku numerów artykułów jako podsekcji) (dla sekcji Uberblick)
WYSWIG_Uberblick.DocumentText = _htmlFactory.GetAllUberblickHTML
Else
TaskDialog.Show(New TaskDialogInfo("Information", eTaskDialogIcon.NoEntry, "Infor", "Critical error occured", eTaskDialogButton.Ok, eTaskDialogBackgroundColor.Blue, Nothing, Nothing, Nothing, "Jakis footer text", Nothing))
e.Cancel = True
End If
ProcessArticle函数:
Public Function ProcessArticle(artikel As ArticlesVariations) As Boolean
Dim result = True
Dim strcon = New AppSettingsReader().GetValue("ConnectionString", GetType(System.String)).ToString()
Using connection As New SqlConnection(strcon)
'-- Open generall connection for all the queries
connection.Open()
'-- Make the transaction.
Dim transaction As SqlTransaction
transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted)
Dim newArticleRowId As Integer = 0
Dim articleIndex As Integer = 0
Try
For Each kvp As KeyValuePair(Of Integer, Artikel) In artikel.collection
Dim ckey As Integer = kvp.Key
articleIndex = kvp.Key 'save article key
Dim data As Artikel = kvp.Value
'-- If given article contains images list (artikel_images is a list with pictures associated with article)
If Not IsNothing(artikel.collection(articleIndex).ArtikelImages) Then
For Each img In artikel.collection(articleIndex).ArtikelImages
'--Insert article's images if exists
Using cmd As New SqlCommand("INSERT INTO T_Article_Image (Path, FK_Artikel_ID, Position) VALUES (@Path, @FK_Artikel_ID, @Position)", connection)
cmd.CommandType = CommandType.Text
cmd.Connection = connection
cmd.Transaction = transaction
cmd.Parameters.AddWithValue("@Path", img.Path)
cmd.Parameters.AddWithValue("@FK_Artikel_ID", newArticleRowId)
cmd.Parameters.AddWithValue("@Position", img.Position)
cmd.ExecuteScalar()
End Using
Next
End If
'-- If given article contains articles variations list (artikel_variation_attributes is a list with variations associated with article)
If Not IsNothing(artikel.collection(articleIndex)._artikel_variation_attributes) Then
For Each var In artikel.collection(articleIndex)._artikel_variation_attributes
'--Insert article's images if exists
Using cmd As New SqlCommand("INSERT INTO T_Artikel_T_Variation (FK_Variation_VariationAttribute_ID, FK_Artikel_ID, Position) VALUES (@FK_Variation_VariationAttribute_ID, @FK_Artikel_ID, @Position)", connection)
cmd.CommandType = CommandType.Text
cmd.Connection = connection
cmd.Transaction = transaction
cmd.Parameters.AddWithValue("@FK_Variation_VariationAttribute_ID", New Variation_VariationAttribute(var.FkVariationId, var.FkVariationAttributeId).GetId())
cmd.Parameters.AddWithValue("@FK_Artikel_ID", newArticleRowId)
cmd.Parameters.AddWithValue("@Position", var.Position)
cmd.ExecuteScalar()
End Using
Next
End If
Next
transaction.Commit()
Catch ex As Exception
result = False
'-- Roll the transaction back.
Try
transaction.Rollback()
Catch ex2 As Exception
' This catch block will handle any errors that may have occurred
' on the server that would cause the rollback to fail, such as
' a closed connection.
'Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType())
'Console.WriteLine(" Message: {0}", ex2.Message)
End Try
End Try
End Using
Return result
End Function
但是,当涉及到错误或其他方法(来自我们的示例)时,一切正常:
Dim resu As Boolean = createArticle.ProcessArticle(_artikelsAndTheirVariationsFinal)
或此方法:
PrepareUberblick()
我的圆形表格没有关闭,但它仍在运行(它被卡住了)。当我Alt+F4
删除我的循环表单时,我看到一条错误消息。我假设发生错误时,错误消息窗口不会显示在前面,但它隐藏在循环表单后面。
以下是问题:您是否知道如何修复它,以便在发生错误时,错误信息显示在前面,以便用户可以确认,然后圆形表格将被关闭?
答案 0 :(得分:0)
如果您想提醒用户发生了某些事情,您可以从圆形表单中显示MessageBox,它应该出现在它上面,因为它是在同一个线程上生成的。您可以在Catch
Try
'--Run lenghty task
resu = createArticle.ProcessArticle(_artikelsAndTheirVariationsFinal)
Catch ex As Exception
pic.Invoke(Sub() MessageBox.Show(ex.message))
End Try
'--Close form once done (on GUI thread)
pic.Invoke(New Action(Sub() pic.StopCircular()))
pic.Invoke(New Action(Sub() pic.Close()))
这样,用户需要在循环表单关闭之前单击MessageBox上的OK。
你的整个问题源于你没有在创建表单的同一个线程上调用MessageBox.Show()这一事实。从您的示例中不清楚创建表单的位置,是否在UI线程上。在任何一种情况下,创建表单的任何线程都必须与引发消息框的线程相同,以便MessageBox对表单进行模态处理。通过调用pic.Invoke(Sub() MessageBox.Show(ex.message))
,您可以确保它显示在表单的主题上,并且将是模态的。您通常可以使用具有
Public Shared Function Show (
owner As IWin32Window,
text As String
) As DialogResult
将是
pic.Invoke(Sub() MessageBox.Show(pic, ex.message))
另见:
Does MessageBox.Show() automatically marshall to the UI Thread?