多线程:动态创建线程,调用WS并报告X个任务

时间:2015-07-31 17:42:45

标签: vb.net multithreading web-services thread-safety threadpool

我是多线程的新手,所以我需要一般指导如何继续。

简而言之,我需要每秒拨打一次外部网络服务数千次。每条记录的响应大约为1秒,如果我有一百万条记录要发送,则效果不佳。所以,我的任务是使用多线程来打开多个线程(数字是动态控制的)来同时调用WS。所以,如果我可以打开100个同时调用WS的线程,那么任务应该在理论上完成得更快......

代码位于底部,我已经删除了很多不必要的部分,所以如果有什么不合理的话请告诉我

这段代码背后的想法是你要调用Threads.Process,传递DataTable需要通过WS发送的数据。此过程将一直运行,直到我们处理数据表中的所有记录,而_threads(其中包含当前正在工作的背景对象列表)中的项目为零。

如果同时线程数允许并且有新数据要处理,

StartThreads将实例化新的后台对象。当后台对象完成其任务时,为了将数据传递回静态对象以记录其数据,它调用Threads.ThreadFinished并将其自身作为参数传递,此时将记录日志信息并从{{中删除backgroundobject 1}}。

然而,在我测试期间,我注意到调用_threads时线程重叠,我试图用SyncLock来抵消它以保持线程安全,但它仍然不能100%傻瓜证明(可能是因为有其他共享功能仍然没有受到保护)。由于我不太了解这种线程,我觉得有一种更简单的方法可以做到这一点。那么,我是在正确的轨道上吗?我应该继续前进还是改用其他方法?我研究了其他多线程方法,比如ThreadPool,但我最终得到了这种方法。

Threads.ThreadFinished

编辑1: 我认为我已经解决了线程被“丢失”的问题 - 基本上我必须在所有Public Class Threads Public Shared Sub ProcessRecords(ByVal dt As DataTable) _threads.Clear() _startTime = Now _dt = dt While Working() StartThreads() Thread.Sleep(100) End While End Sub Private Shared Sub StartThreads() While _threads.Count < Settings.NumberOfThreads AndAlso _rowCounter < _dt.Rows.Count Dim id As String = GetRandomChar(, 20) ' Generate a random ID for logging purposes Dim tw As New ThreadWorker(_dt.Rows(_rowCounter), _rowCounter, id, _dt.Rows(_rowCounter)("id").ToString()) _rowCounter += 1 _threads.Add(tw) End While End Sub Public Shared Sub ThreadFinished(ByVal tw As ThreadWorker) SyncLock tw Log(tw.Log) _threads.Remove(tw) End SyncLock StartThreads() End Sub Private Shared Function Working() As Boolean Return _rowCounter < _dt.Rows.Count OrElse _threads.Count > 0 End Function End Class Public Class ThreadWorker Private _bw As System.ComponentModel.BackgroundWorker Private _logDebug As New StringBuilder Sub New(ByVal dr As DataRow) _bw = New System.ComponentModel.BackgroundWorker _bw.WorkerReportsProgress = True _bw.WorkerSupportsCancellation = True AddHandler _bw.DoWork, AddressOf bw_Working AddHandler _bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted _bw.RunWorkerAsync() End Sub Private Sub bw_Working(ByVal Sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) ' Call webservice ... _logDebug.AppendLine("Response from WS") End Sub Public Sub bw_RunWorkerCompleted(ByVal Sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _logDebug.AppendLine("Job completed") Threads.ThreadFinished(Me) End Sub End Class 函数中SyncLock _threadsShared似乎没有做到这一点)。尽管如此,这充其量只是肮脏和骇人听闻。我觉得有更好的办法。我目前正在研究ThreadPool方法,但我有点因为它的线程限制而被推迟。我可能需要打开数千个线程。

我注意到的是,我打开的并发线程越多,从WS获得初始响应所需的时间就越长。例如,如果我一次只处理1个记录/线程,则需要1秒钟才能从WS获得响应。如果我打开100个线程,则需要一分钟才能得到响应。我怀疑网络在这里屈服,或者它的窗口限制?

0 个答案:

没有答案