У моего приложения есть некоторый длинный метод, который занимает некоторое время, чтобы быть завершенным, поэтому я решил вставить его в отдельную задачу, а затем показать некоторые новые форму как ShowDialog
, внутри которой размещена анимация песочных часов, а затем эта форма должна быть закрыта, когда задача завершила работу. В тот момент ситуация заключается в том, что моя новая форма ожидания не собирается закрываться при ее просто появлении и пребывании. Я где-то читал, потому что ShowDialog
в этом случае ничего не вернет, поэтому Close
никогда не будет достигнут, пока пользователь не нажмет Закрыть вручную по форме, но как его возможно, как если бы я положил form.Close
, он должен быть таким же, как пользователь будет нажимать на эту форму , Пожалуйста, объясните и поддержите здесь, что нужно изменить для достижения цели. Ниже моего кода.Положите метод long running в задачу, показывая новую форму и закрыв ее после завершения задачи
Главная форма:
WinScp = New WinScpOperation("ftp", "myserver", "login", "password", 21, 0)
Dim tsk As Task(Of Boolean) = Task.Factory.StartNew(Of Boolean)(Function()
Return WinScp.GetFile(myremotePicturePath, ladujZdjeciaPath, True)
End Function)
Dim pic As New Waiting
pic.ShowDialog() 'show waiting form
Task.WaitAll(tsk) 'waiting on task to be finalized
pic.Close() 'close waiting form
...
Ожидание формы (ничего, кроме песочных GIF)
Public Class Waiting
End Class
Дальнейшее обсуждение # 1:
Вариант 1: (ваша рабочая версия)
Dim pic As New Waiting
Dim tsk As Task(Of Boolean) =
Task.Factory.StartNew(Of Boolean)(
Function()
' Run lenghty task
Dim Result As Boolean = WinScp.GetFile(myremotePicturePath, ladujZdjeciaPath, True)
' Close form once done (on GUI thread)
pic.Invoke(New Action(Sub() pic.Close()))
Return Result
End Function)
' Show the form
pic.ShowDialog()
Task.WaitAll(tsk)
Option2: (не работает, почему ??)
Dim pic As New Waiting
Dim tsk As Task(Of Boolean) =
Task.Factory.StartNew(Of Boolean)(
Function()
' Run lenghty task
Dim Result As Boolean = WinScp.GetFile(myremotePicturePath, ladujZdjeciaPath, True)
Return Result
End Function)
' Show the form
pic.ShowDialog()
Task.WaitAll(tsk)
' Close form once done (on GUI thread)
pic.Invoke(New Action(Sub() pic.Close()))
Дополнительный вопрос:
Dim pic As New Waiting
Dim tsk As Task(Of Boolean) =
Task.Factory.StartNew(Of Boolean)(
Function()
' Run lenghty task
Dim Result As Boolean = WinScp.GetFile(myremotePicturePath, ladujZdjeciaPath, True)
' Close form once done (on GUI thread)
pic.Invoke(New Action(Sub() pic.Close()))
Return Result
End Function)
' Show the form
pic.ShowDialog()
Task.WaitAll(tsk)
If tsk.Result Then 'if return value is true
'Do something when file was downloaded correctly
Else
'Do something when file was NOT downloaded
End If
Дополнительный # 2: Это было oryginally:
If WinScp.GetFile(lsbxPicPaths.SelectedItem, temp_dir & "\" & Path.GetFileName(lsbxPicPaths.SelectedItem), False) Then
temp_pic = temp_dir & "\" & Path.GetFileName(lsbxPicPaths.SelectedItem)
End If
Я реализовал наше решение:
Dim pic As New Waiting
Dim tsk As Task(Of Boolean) =
Task.Factory.StartNew(Of Boolean)(
Function()
Run lenghty task
Dim Result As Boolean = WinScp.GetFile(lsbxPicPaths.SelectedItem, temp_dir & "\" & Path.GetFileName(lsbxPicPaths.SelectedItem), False)
' Close form once done (on GUI thread)
pic.Invoke(New Action(Sub() pic.Close()))
Return Result
End Function)
' Show the form
pic.ShowDialog()
Task.WaitAll(tsk)
If tsk.Result Then 'if return value is true
temp_pic = temp_dir & "\" & Path.GetFileName(lsbxPicPaths.SelectedItem)
' Else
End If
'*************************************
Решение к выше: понятия не имею, почему, когда определены две переменные вместо непосредственно положить его в аргументы GetFile решить, потому что ранее также не было переменных и работает. Может ли кто-нибудь объяснить это поведение?
Dim remotefile As String = lsbxPicPaths.SelectedItem
Dim temp_file As String = temp_dir & "\" & Path.GetFileName(lsbxPicPaths.SelectedItem)
'http://stackoverflow.com/questions/33030706/put-long-running-method-into-task-showing-new-form-meantime-and-closing-it-once
Dim pic2 As New Waiting
Dim tsk2 As Task(Of Boolean) = Task.Factory.StartNew(Of Boolean)(Function()
'Run lenghty task
Dim Result As Boolean = WinScp.GetFile(remotefile, temp_file, False)
'Close form once done (on GUI thread)
pic2.Invoke(New Action(Sub() pic2.Close()))
Return Result
End Function)
pic2.ShowDialog()
Task.WaitAll(tsk2)
If tsk2.Result = True Then
MsgBox("GetFile zwrocilo true")
temp_pic = temp_dir & "\" & Path.GetFileName(lsbxPicPaths.SelectedItem)
End If
отличная работа !! Во всяком случае, я не могу понять, как это работает - посмотрите мой главный пост, пожалуйста. Вариант 1 - ваш код - никаких проблем. Вариант 2 - почему, когда move вызывает внешнюю разделенную нить, он не будет работать, так же, как если бы я просто поместил pic.Close? Не могу понять, почему я должен назвать это из второй разделенной нити? – Arie
Поскольку метод ShowDialog является методом блокировки. Он работает до тех пор, пока форма открывается. Не похоже, что форма и код продолжаются на следующей строке. Он останавливается на вызове ShowDialog, и вы не можете ничего сделать в этом (GUI) потоке. 'ShowDialog' запускает цикл внутри. Поэтому вам нужно нарушить цикл извне, вызвав '.Close'. –
так просто говорить, что я не могу просто поместить pic.Close или pic.Invoke (новое действие (Sub() pic.Close())) из того же самого потока gui правильно (опция 2)? Я должен делать это из разделенной нити, как в нашем случае tsk do? – Arie