Как сделать очень простой асинхронный вызов метода в vb.net

У меня просто простой веб-сайт vb.net, которому нужно вызвать Sub, который выполняет очень длинную задачу, которая работает с синхронизацией некоторых каталогов в файловой системе (подробности не важны).

Когда я вызываю метод, он в конечном итоге истекает на веб-сайте, ожидая завершения подпрограммы. Однако, несмотря на то, что веб-сайт не работает, подпрограмма в конечном итоге завершает работу, и все каталоги заканчиваются так, как должны.

Я хочу просто запретить таймаут, поэтому я бы хотел просто вызвать Sub асинхронно. Мне не нужно (или даже хочу) и обратный вызов/подтверждение того, что он успешно выполнен.

Итак, как я могу назвать свой метод асинхронно внутри веб-сайта с помощью VB.net?

Если вам нужен какой-то код:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Call DoAsyncWork()
End Sub

Protected Sub DoAsyncWork()
        Dim ID As String = ParentAccountID
        Dim ParentDirectory As String = ConfigurationManager.AppSettings("AcctDataDirectory")
        Dim account As New Account()
        Dim accts As IEnumerable(Of Account) = account.GetAccounts(ID)

        For Each f As String In My.Computer.FileSystem.GetFiles(ParentDirectory)
            If f.EndsWith(".txt") Then
                Dim LastSlashIndex As Integer = f.LastIndexOf("\")
                Dim newFilePath As String = f.Insert(LastSlashIndex, "\Templates")
                My.Computer.FileSystem.CopyFile(f, newFilePath)
            End If
        Next

        For Each acct As Account In accts
            If acct.ID <> ID Then
                Dim ChildDirectory As String = ConfigurationManager.AppSettings("AcctDataDirectory") & acct.ID
                If My.Computer.FileSystem.DirectoryExists(ChildDirectory) = False Then
                    IO.Directory.CreateDirectory(ChildDirectory)
                End If
                My.Computer.FileSystem.DeleteDirectory(ChildDirectory, FileIO.DeleteDirectoryOption.DeleteAllContents)
                My.Computer.FileSystem.CopyDirectory(ParentDirectory, ChildDirectory, True)
            Else
            End If
        Next
End Sub

Ответы

Ответ 1

Я бы не рекомендовал использовать класс Thread, если вам не нужен намного больше контроля над потоком, так как создание и отключение потоков является дорогостоящим. Вместо этого я бы рекомендовал использовать поток ThreadPool. См. это для хорошего чтения.

Вы можете выполнить свой метод в потоке ThreadPool следующим образом:

System.Threading.ThreadPool.QueueUserWorkItem(AddressOf DoAsyncWork)

Вам также необходимо изменить свою подпись метода на...

Protected Sub DoAsyncWork(state As Object) 'even if you don't use the state object

Наконец, также помните, что необработанные исключения в других потоках будут убивать IIS. См. в этой статье (старый, но по-прежнему актуальный, не уверен в решениях, хотя, поскольку я не использую ASP.NET).

Ответ 2

Вы можете сделать это с помощью простого потока:

Добавить:

 Imports System.Threading

И везде, где вы хотите его запустить:

 Dim t As New Thread(New ThreadStart(AddressOf DoAsyncWork))
 t.Priority = Threading.ThreadPriority.Normal
 t.Start()

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

Ответ 3

Я также искал информацию о асинхронном программировании в VB. В дополнение к этой теме я также нашел следующее: начиная с Visual Studio 2012 и .Net Framework 4.5, VB было предоставлено два новых ключевых слова, чтобы сделать метод асинхронным в декларации без использования Thread или Threadpool. Новые ключевые слова: "Async" и "Await". Вы можете ссылаться на следующие ссылки:

http://msdn.microsoft.com/library/hh191443%28vs.110%29.aspx

https://msdn.microsoft.com/en-us/library/hh191564%28v=vs.110%29.aspx

Ответ 4

Это старая ветка, но я решил, что все равно добавлю к ней, поскольку недавно мне нужно было решить эту проблему. Если вы хотите использовать ThreadPool для вызова метода с параметрами, вы можете изменить пример @Timiz0r следующим образом:

System.Threading.ThreadPool.QueueUserWorkItem(Sub() MethodName( param1, param2, ...))