如何在vb.net中进行非常简单的异步方法调用

14
我有一个简单的vb.net网站,需要调用一个子程序,该子程序执行与文件系统中某些目录同步的非常长时间的任务(细节不重要)。
当我调用该方法时,网站最终会超时等待子例程完成。然而,即使网站超时,该例程最终也会完成其任务,并且所有目录都会按照预期进行更新。
我想要防止超时,因此我想异步调用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
4个回答

23
我不建议使用 Thread 类,除非您需要更多控制线程,因为创建和销毁线程是昂贵的。相反,我建议使用 线程池线程。可以像这样在 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,所以不确定其中的解决方案)。


这对我非常有效,我将文件上传到Web服务器。验证文件,然后通过电子邮件发送它。即使用户关闭了网页/站点/浏览器,电子邮件仍然可以到达目的地。 - htm11h
谢谢您!非常有效,现在我只需要从线程池更新GUI。 - RBILLC

7
你可以使用简单的线程来实现这一点:
添加:
 Imports System.Threading

无论您想在哪里运行它:

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

t.Start() 的调用会立即返回,新线程在后台运行 DoAsyncWork 直到完成。您必须确保该调用中的所有内容都是线程安全的,但乍一看似乎已经是了。


完美回答 +1,但我更喜欢使用线程池的想法来保持简单和轻量级。 - RichC
@EdenMachine 我同意,线程池可能是更好的选择。 - J...

0

这是一个较旧的线程,但我认为我应该添加一些内容,因为我最近需要解决这个问题。如果您想使用线程池调用带参数的方法,您可以修改@Timiz0r的示例如下:

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

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接