2014-12-17 4 views
-1

Пожалуйста, смотрите ниже код, который я адаптировано из следующей веб-странице: http://www.codeguru.com/csharp/csharp/introduction-to-async-and-await-keywords-in-c-5.0.htmОжидать причинения основного потока?

Public Class Form1 

    Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load 
     Dim program As New Program() 
     Await program.PrintSumAsync() 
     MsgBox("got here 1") 
    End Sub 
End Class 

Class Program 

    Public Async Function PrintSumAsync() As Task 
     Dim value1 As Integer = Await GetValueAsync() 
     Dim value2 As Integer = Await GetValueAsync() 

     Console.WriteLine("Sum of two random numbers is: {0}", value1 + value2) 
    End Function 

    Private Async Function GetValueAsync() As Task(Of Integer) 
     System.Threading.Thread.Sleep(5000) 
     Dim random As Integer = ComputeValue() 
     Return random 
    End Function 


    Private Function ComputeValue() As Integer 
     MsgBox("got here 2") 
     Return New Random().[Next](1, 1000) 

    End Function 
End Class 

я добавил вызов в режим сна в GetValueAsync так, что она занимает некоторое время, чтобы закончить.

Я ожидал, что код достигнет msgbox1 (получил здесь 1) до msgbox2 (получил здесь 2). Ожидание, кажется, останавливает основной поток. Что мне не хватает? У меня нет опыта работы с ключевым словом newish. Недавно я обновился от .NET до .NET 4.5.2.

Update основе Davids ответа я редактировал код следующим образом:

Public Class Form1 

    Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load 
     test() 
     MsgBox("got here 1") 
    End Sub 

    Public Async Sub test() 
     Dim program As New Program() 
     Await program.PrintSumAsync() 
     'Dim task As Task = program.PrintSumAsync() 
     MsgBox("got here 2") 
    End Sub 
End Class 

Class Program 

    Public Async Function PrintSumAsync() As Task 
     Dim value1 As Integer = Await GetValueAsync() 
     Dim value2 As Integer = Await GetValueAsync() 

     Console.WriteLine("Sum of two random numbers is: {0}", value1 + value2) 
    End Function 

    Private Async Function GetValueAsync() As Task(Of Integer) 
     Try 
      Await Task.Delay(5000) 
      Dim random As Integer = ComputeValue() 
      Return random 
     Catch ex As Exception 
      MsgBox(ex.ToString) 
     End Try 
    End Function 


    Private Function ComputeValue() As Integer 
     MsgBox("got here 2") 
     Return New Random().[Next](1, 1000) 
    End Function 
End Class 

Как я могу остановить основной поток от отделки до того окна сообщений 2 появится?

ответ

4

Await не останавливает основной поток, вы:

System.Threading.Thread.Sleep(5000) 

Там нет ничего асинхронным происходит в этом методе:

Private Async Function GetValueAsync() As Task(Of Integer) 
    System.Threading.Thread.Sleep(5000) 
    Dim random As Integer = ComputeValue() 
    Return random 
End Function 

(Я удивлен, что компилятор не жалуясь на это. Он работает с C#.) Таким образом, хотя код и код использования метода украшены ключевыми словами Async и Await, полученный код на самом деле не является асинхронным. Это может быть, однако, если вы ожидаете асинхронной операции в этом методе. Например:

Private Async Function GetValueAsync() As Task(Of Integer) 
    Await Task.Delay(5000) 
    Dim random As Integer = ComputeValue() 
    Return random 
End Function 

Это приведет к асинхронному действию целого ряда операций, в результате чего будут использованы новые ключевые слова.

Обратите внимание, однако, что наблюдаемые результаты, вероятно, будут оставаться прежними. Посмотрите на метод верхнего уровня:

Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load 
    Dim program As New Program() 
    Await program.PrintSumAsync() 
    MsgBox("got here 1") 
End Sub 

Код в этом методе все еще не собирается, чтобы выполнить третью строчку, пока после того, как вторая линия не ждали до завершения. очень верхний уровень (пользовательский интерфейс, вызывающий этот обработчик) будет продолжаться, не дожидаясь этого метода, но этот метод будет ожидать завершения его асинхронных операций до его продолжения.

Для того, чтобы получить результат, который вы ищете, вам нужно будет захватить Task, а не ждать его. Что-то вроде этого:

Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load 
    Dim program As New Program() 
    Dim task As Task = program.PrintSumAsync() 
    MsgBox("got here 1") 
    ' do something with the task object. 
    ' await it, provide it with a callback function for when it completes, etc. 
End Sub 

В Async и Await ключевые слова не обязательно делать функции произойдет в новом потоке. Для большинства целей и целей вы можете очень часто воспринимать их как просто синтаксическую стенографию для обертывания части метода в ContinueWith() на объекте Task. В любом данном методе Async должно быть Await, на котором можно разместить ContinueWith(). Если в нем нет Await, то метод Async не является асинхронным.

+0

Thanks +1. Я отредактировал вопрос, основываясь на вашем ответе. Не могли бы вы взглянуть? – w0051977

+0

@ w0051977: Я не уверен, что задает ваш обновленный вопрос. Не отображаются ли окна сообщений в обновленном коде? Какое поведение вы видите и чего пытаетесь достичь? Мне непонятно, что вы подразумеваете под «прекращением основной нити до окончания». – David

+0

Во втором фрагменте кода я не хочу, чтобы основной поток заканчивался, пока не закончились два асинхронных вызова. Имеет ли это смысл? – w0051977

1

Просто для крупы и голени, играйте с этим. Мне казалось, как процесс получения случайных значений должны быть запущены в параллельно:

Public Class Form1 

    Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
     Button1.Enabled = False 
     Label1.Text = DateTime.Now 
     Label2.Text = "" 

     Await test() 

     Label2.Text = DateTime.Now 
     Button1.Enabled = True 
    End Sub 

    Public Async Function test() As Task 
     Dim program As New Program() 
     Await Task.Run(New Action(AddressOf program.PrintSum)) 
    End Function 

End Class 

Class Program 

    Private R As New Random 

    Public Sub PrintSum() 
     ' get some random values IN PARALLEL and wait for them all to finish 
     Dim tasks As New List(Of Task(Of Integer)) 
     For i As Integer = 1 To 5 
      tasks.Add(Task(Of Integer).Factory.StartNew(Function() GetValue())) 
     Next 
     Task.WaitAll(tasks.ToArray) 
     Dim sum As Integer = 0 
     For i As Integer = 0 To tasks.Count - 1 
      sum = sum + tasks(i).Result 
     Next 
     Console.WriteLine("Sum of the random numbers is: " & sum) 
    End Sub 

    Private Function GetValue() As Integer 
     Console.WriteLine("Getting value...") 
     System.Threading.Thread.Sleep(R.Next(3000, 10001)) ' random 3 to 10 second delay 
     Return ComputeValue() 
    End Function 

    Private Function ComputeValue() As Integer 
     Dim i As Integer = R.Next(1, 1000) 
     Console.WriteLine("Value selected: " & i) 
     Return i 
    End Function 

End Class 
+0

Это было спасибо. +1. – w0051977

Смежные вопросы