处理任务最有效的方法
Most efficient way to handle tasks
我有一个 windows 表单程序,它 运行 24/7 运行,大约每 15 分钟做一些工作,然后必须进行大约 5000 次 http 调用,我不需要等待或从调用中获得任何结果,只需点击 http API 并继续。我将 http 调用作为一个单独的子程序,而我现在所做的只是为每个调用生成一个新线程。这在高 CPU 机器上工作正常,但是当我 运行 在有限 CPU 的托管机器上时,我得到大约 1/5 的线程错误并出现 HTTP 超时。
所以我的问题是如何独立于我的主线程处理 5000 多个子调用,以便尽可能快地处理它们而不阻塞我的应用程序
这是现在的基本代码:
for i = 1 to 5000
Dim thread As New Thread(
Sub()
sendtoapi(i)
End Sub
)
thread.SetApartmentState(ApartmentState.STA)
Thread.Start()
next i
Private Sub sendtoapi(i as integer)
Dim result As String = ""
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Using Client As New System.Net.WebClient()
result = Client.DownloadString("https://apiurl/addnumber?num=" & i)
End Using
End Sub
您可以使用任务并行库限制线程数。即,Parallel.For
。这将很好地替代您的 For
循环。
Parallel.For(1, 5001, Sub(i) sendtoapi(i))
由于您是从表单计时器执行的 运行,因此您可以继续执行此操作并使用 Async/Await
机制进行较小的更改。
Private WithEvents Timer1 As New System.Windows.Forms.Timer _
With {.Enabled = True, .Interval = 15 * 60 * 1000}
Private Async Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Await Task.Run(Sub() Parallel.For(1, 5001, Sub(i) sendtoapi(i)))
End Sub
这实际上并没有创建新线程,而是使用线程池中的现有线程。好吧,在 TPL 内部肯定会创建新线程 :) 但 Async/Await
本身不会。
您完全可以使用 System.Threading.Timer
将其从 UI 中删除,而无需担心会阻塞 UI。这 运行s 在线程池线程上,TPL 将管理它是利用线程池线程还是觉得需要生成新线程。无论哪种方式,它都会让您的系统处于控制之中。
Private runTimer As New System.Threading.Timer(AddressOf run, Nothing, 0, 15 * 60 * 1000)
Sub run(state As Object)
Parallel.For(1, 5001, Sub(i) sendtoapi(i))
End Sub
我有一个 windows 表单程序,它 运行 24/7 运行,大约每 15 分钟做一些工作,然后必须进行大约 5000 次 http 调用,我不需要等待或从调用中获得任何结果,只需点击 http API 并继续。我将 http 调用作为一个单独的子程序,而我现在所做的只是为每个调用生成一个新线程。这在高 CPU 机器上工作正常,但是当我 运行 在有限 CPU 的托管机器上时,我得到大约 1/5 的线程错误并出现 HTTP 超时。
所以我的问题是如何独立于我的主线程处理 5000 多个子调用,以便尽可能快地处理它们而不阻塞我的应用程序
这是现在的基本代码:
for i = 1 to 5000
Dim thread As New Thread(
Sub()
sendtoapi(i)
End Sub
)
thread.SetApartmentState(ApartmentState.STA)
Thread.Start()
next i
Private Sub sendtoapi(i as integer)
Dim result As String = ""
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Using Client As New System.Net.WebClient()
result = Client.DownloadString("https://apiurl/addnumber?num=" & i)
End Using
End Sub
您可以使用任务并行库限制线程数。即,Parallel.For
。这将很好地替代您的 For
循环。
Parallel.For(1, 5001, Sub(i) sendtoapi(i))
由于您是从表单计时器执行的 运行,因此您可以继续执行此操作并使用 Async/Await
机制进行较小的更改。
Private WithEvents Timer1 As New System.Windows.Forms.Timer _
With {.Enabled = True, .Interval = 15 * 60 * 1000}
Private Async Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Await Task.Run(Sub() Parallel.For(1, 5001, Sub(i) sendtoapi(i)))
End Sub
这实际上并没有创建新线程,而是使用线程池中的现有线程。好吧,在 TPL 内部肯定会创建新线程 :) 但 Async/Await
本身不会。
您完全可以使用 System.Threading.Timer
将其从 UI 中删除,而无需担心会阻塞 UI。这 运行s 在线程池线程上,TPL 将管理它是利用线程池线程还是觉得需要生成新线程。无论哪种方式,它都会让您的系统处于控制之中。
Private runTimer As New System.Threading.Timer(AddressOf run, Nothing, 0, 15 * 60 * 1000)
Sub run(state As Object)
Parallel.For(1, 5001, Sub(i) sendtoapi(i))
End Sub