Просто вступайте в асинхронное программирование, и моя конечная цель заключается в том, чтобы асинхронно получить хэши sha1 заданного набора файлов, а затем продолжить обработку указанных файлов с вычисленным значением хэша. Я обнаружил, что следующее сообщение в блоге MSDN говорит о том, как обрабатывать результаты задачи по завершении задач: LinkИспользуйте await без async для обработки задач по мере их завершения.
Вся статья написана на C#, а мой проект - на VB.NET. Я попытался переписать код C# на сам VB, однако мне не хватает критического шага или я не полностью понимаю процесс/синтаксис программирования Async
/Await
.
Я получаю следующее сообщение об ошибке в следующих строках:
Ошибка 1 «Await» может быть использована только тогда, когда содержится в выражении метода или лямбда-помеченной модификатором «Асинхронный».
Dim t As Task(Of Integer) = Await bucket
Dim result As Integer= Await t
Dim t As Task(Of String) = Await bucket
Dim result As String = Await t
Я могу сделать ошибку уйти, добавив Async
к охватывающему Суб декларации. Однако, если я это сделаю, я получаю еще одну ошибку, потому что метод содержания - main()
, и это консольное приложение.
Ошибка 1 Метод «Основной» не может быть помечен как «Асинхронный».
Так что я думаю, мой вопрос в том, как я могу использовать Await
асинхронную задачу без создания метода Async? Мой код ниже - это просто тестер для реализации в проекте WinForms, и я предпочел бы держаться подальше от не-родных .NET-штук.
Ниже приведен полный код, который я преобразован из C# вместе с моей немного кода, который делает вычисления из SHA1 хэшей для файлов:
Option Strict On
Option Explicit On
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Module Module1
Async Sub main()
' From the MSDN article
Dim taskArr As Task(Of Integer)() = {Task(Of Integer).Delay(3000).ContinueWith(Function(x) 3I), _
Task(Of Integer).Delay(1000).ContinueWith(Function(x) 1I), _
Task(Of Integer).Delay(2000).ContinueWith(Function(x) 2I), _
Task(Of Integer).Delay(5000).ContinueWith(Function(x) 5I), _
Task(Of Integer).Delay(4000).ContinueWith(Function(x) 4I)}
For Each bucket As Task(Of Task(Of Integer)) In Interleaved(taskArr)
Dim t As Task(Of Integer) = Await bucket ' Error Here
Dim result As Integer = Await t ' Error Here
Console.WriteLine("{0}: {1}", DateTime.Now, result)
Next
'My bit of code for computing the file hashes
Dim tasks As New List(Of Task(Of String))
Array.ForEach(New DirectoryInfo("C:\StackOverflow").GetFiles("*", SearchOption.AllDirectories), Sub(x) tasks.Add(getHashAsync(x)))
For Each bucket As Task(Of Task(Of String)) In Interleaved(tasks)
Dim t As Task(Of String) = Await bucket ' Error Here
Dim result As String = Await t ' Error Here
Console.WriteLine(result)
Next
End Sub
' Original C# code that I converted to VB myself
Public Function Interleaved(Of T)(tasks As IEnumerable(Of Task(Of T))) As Task(Of Task(Of T))()
Dim inputTasks As List(Of Task(Of T)) = tasks.ToList()
Dim buckets() As TaskCompletionSource(Of Task(Of T)) = New TaskCompletionSource(Of Task(Of T))(inputTasks.Count - 1I) {}
Dim results() As Task(Of Task(Of T)) = New Task(Of Task(Of T))(buckets.Length - 1I) {}
For i As Integer = 0I To buckets.Count - 1I Step 1I
buckets(i) = New TaskCompletionSource(Of Task(Of T))()
results(i) = buckets(i).Task
Next
Dim continuation As New Action(Of Task(Of T))(Function(completed As Task(Of T))
Dim bucket As TaskCompletionSource(Of Task(Of T)) = buckets(Interlocked.Increment(-1I))
Return bucket.TrySetResult(completed)
End Function)
For Each inputTask As Task(Of T) In inputTasks
inputTask.ContinueWith(continuation, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default)
Next
Return results
End Function
' Get the sha1 hash of the file
Private Async Function getHashAsync(fle As FileInfo) As Task(Of String)
Using strm As New IO.FileStream(fle.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)
Return Await New Task(Of String)(Function() As String
Dim sb As New Text.StringBuilder()
Using sha1 As New System.Security.Cryptography.SHA1CryptoServiceProvider()
Array.ForEach(sha1.ComputeHash(strm), Sub(x As Byte) sb.Append(x.ToString("x2")))
End Using
Return sb.Append(" | ").Append(fle.FullName).ToString
End Function)
End Using
End Function
End Module
Я не уверен, что этот конкретный случай является хорошим кандидатом на ожидание/асинхронный процесс, поскольку это все в основном работа с ЦП, которая должна быть отключена. Достаточно использовать только «Задачи» и доступные возможности ожидания и результаты. @VMAtm предоставил хороший ответ для этого ниже. Когда вы входите в создание приложения WinForms, вы сможете украсить свои события или контроллеры Async, чтобы асинхронный/ожидающий способ мог распространяться на выполнение вашего приложения, если это необходимо. – davidallyoung