C# 多线程
我正在开发一个应用程序(用C#)。这基本上是一个文件上传/下载应用程序(就像filezila) 但有一个特殊功能(文件下载):- 我们可以将一个文件分成不同的部分(最多100个)。并且可以通过不同的周期重复这个过程(意味着我们可以将一个文件分成不同的段,并且可以同时重复这个过程多次(通过周期) 在应用程序中有一些进度条和标签显示上传/下载状态 我的问题是:- 如果我对更多号码执行此过程(下载),例如:- 100次循环和(循环可以超过100次) 100段 这意味着我们将一个文件分为100个部分(段),相同的过程将工作100次(周期) 意味着100*100=10000个文件将通过相同的过程同时下载 但我面临的问题是,若我为这项任务接受了大量的数据,那个么就会有更多的线程打开 如果有100个TCP端口/线程同时运行,应用程序将挂起 我为此做了很多尝试,但还没有成功- 异步委托、线程池等 我在更新进度条和标签时面临一个主要问题(因为当前的功能与异步委托一起工作)C# 多线程,c#,.net,winforms,multithreading,C#,.net,Winforms,Multithreading,我正在开发一个应用程序(用C#)。这基本上是一个文件上传/下载应用程序(就像filezila) 但有一个特殊功能(文件下载):- 我们可以将一个文件分成不同的部分(最多100个)。并且可以通过不同的周期重复这个过程(意味着我们可以将一个文件分成不同的段,并且可以同时重复这个过程多次(通过周期) 在应用程序中有一些进度条和标签显示上传/下载状态 我的问题是:- 如果我对更多号码执行此过程(下载),例如:- 100次循环和(循环可以超过100次) 100段 这意味着我们将一个文件分为100个部分(段
请为我提供一些解决此问题的方法。因为所有这些线程都希望向UI线程传递数据以显示进度,UI线程正在成为应用程序的瓶颈 您可以添加一个计时器,使UI线程时不时地检查作业的进度 这样,UI线程不是由大量线程驱动的,而是由时间驱动的
如果您需要更多详细信息,请发布一些代码。你好,Erno为了更好地理解,我将发送一些代码:- 这是下载功能:
Public Sub FileDownload()
txtBytesToDownload.Text = totalBytesToDownload.ToString("N", nfi) 'set textbox with total file size
del = New MyDelegate(AddressOf DownloadDataInRange)
callback = New AsyncCallback(AddressOf CalcCallback)
TotalBytesToDownloadForEachCycle = totalBytesToDownload
downloadedBytes = 0
dlStopWatch = Stopwatch.StartNew()
Dim flag As Integer = 0
Dim segment As Integer = nuSegment.Value 'total segments
Dim cyl = cycleNumericUpDown.Value 'total cycles
'ServicePointManager.DefaultConnectionLimit = segment
If UtilityFunctions.CheckRangeSupported(dlUrlHttpTextBox.Text) Then
Dim segmentSize As Integer = 0
segmentSize = TotalBytesToDownloadForEachCycle / segment
' For cy As Integer = 0 To (cyl - 1)
For ctr As Integer = 0 To (segment - 1) 'loop for total Segments
GC.Collect()
flag += 1
Dim fileValues As New FileValues()
If ctr = 0 Then
fileValues.StartPoint = 0 'starting point of each segment (in bytes)
Else
fileValues.StartPoint = segmentSize * ctr + 1
End If
fileValues.EndPoint = fileValues.StartPoint + segmentSize 'end point of each segment (in bytes)
If (ctr = (segment - 1)) Then
fileValues.EndPoint += TotalBytesToDownloadForEachCycle Mod segment
End If
fileValues.URL = dlUrlHttpTextBox.Text 'downloading file url
Dim str As String = ctr.ToString() + "_" + flag.ToString()
' del.BeginInvoke(fileValues, callback, Nothing)
newThread = New System.Threading.Thread(AddressOf DownloadBytes) 'Thread starts here
newThread.Priority = ThreadPriority.Highest
newThread.IsBackground = True
newThread.Start(fileValues)
'ThreadPool.QueueUserWorkItem(AddressOf DownloadBytes, fileValues)
fileValues = Nothing
Next
' ProgressBarTotal.Value += 1
' Next
Else
Dim fileValues As New FileValues()
fileValues.StartPoint = 0
fileValues.EndPoint = TotalBytesToDownloadForEachCycle
fileValues.URL = dlUrlHttpTextBox.Text
Dim newThread As New System.Threading.Thread(AddressOf DownloadBytes)
newThread.Name = "Thread1"
newThread.Start(fileValues)
'ThreadPool.QueueUserWorkItem(AddressOf DownloadBytes, fileValues)
fileValues = Nothing
End If
Console.WriteLine("Http Downloload End")
Debug.Print("thread List 1 count =" + _threadsList1.Count.ToString() + ", thread list 2 count =" + _threadsList2.Count.ToString() + ", thread list 3 count =" + _threadsList3.Count.ToString())
'MessageBox.Show("finished - flag=" + flag.ToString())
'After all Cycles Complete
'startButton.Enabled = True
'abortButton.Enabled = False
'skipButton.Enabled = False
'DataGridViewDLOrPing.Enabled = True
'DataGridViewUL.Enabled = True
'protocolComboBox.Enabled = True
'modelComboBox.Enabled = True
'testTypeComboBox.Enabled = True
'measurementComboBox.Enabled = True
'cycleNumericUpDown.Enabled = True
'DelayNumericUpDown.Enabled = True
'InputBoxPrivilege()
End Sub
这是线程将调用以读取字节的函数:
Public Sub DownloadBytes(ByVal p_fileValues As FileValues)
Dim httpWebRequest As HttpWebRequest
Dim httpWebResponse As HttpWebResponse
Dim responseStream As Stream
Dim threadName = threadID
Try
Console.WriteLine("Start " + Thread.CurrentThread.Name)
httpWebRequest = DirectCast(WebRequest.Create(p_fileValues.URL), HttpWebRequest)
'httpWebRequest.ProtocolVersion = HttpVersion.Version11
httpWebRequest.KeepAlive = False
httpWebRequest.AddRange(p_fileValues.StartPoint, p_fileValues.EndPoint)
httpWebRequest.Credentials = CredentialCache.DefaultCredentials
httpWebRequest.Proxy = WebRequest.DefaultWebProxy
httpWebResponse = CType(httpWebRequest.GetResponse(), HttpWebResponse)
responseStream = httpWebResponse.GetResponseStream()
Dim bytesSize As Integer = 0
' A buffer for storing and writing the data retrieved from the server
Dim downBuffer As Byte() = New Byte(2047) {}
Dim bytesAlreadyDownloaded As Int64 = p_fileValues.StartPoint
' Loop through the buffer until the buffer is empty
While (True)
'end while loop if the Abort button is clicked
If (isActionAborted = True) Then
Exit While
End If
'currentCycle is > total Cycles ,then end while
If (currentCycleDownload > cycleNumericUpDown.Value) Then
Exit While
End If
bytesSize = responseStream.Read(downBuffer, 0, downBuffer.Length)
bytesAlreadyDownloaded += bytesSize
'speedtimer.Start()
If (bytesSize <= 0) Then
If (downloadedBytes < totalBytesToDownload) Then
Me.Invoke(New UploadProgressCallback(AddressOf Me.UpdateDownloadProgress), New Object() {(totalBytesToDownload - downloadedBytes), totalBytesToDownload})
End If
Exit While
End If
' Invoke the method that updates the form's label and progress bar
Me.Invoke(New DownloadProgressCallback(AddressOf Me.UpdateDownloadProgress), New Object() {bytesSize, TotalBytesToDownloadForEachCycle})
If (bytesAlreadyDownloaded > p_fileValues.EndPoint) Then
'Console.WriteLine("Downloading part files Exit " + p_fileValues.StartPoint.ToString() + "," + p_fileValues.EndPoint.ToString())
Exit While
End If
End While
responseStream.Flush()
responseStream.Close()
httpWebResponse.Close()
responseStream.Dispose()
responseStream = Nothing
httpWebResponse = Nothing
Console.WriteLine("End " + Thread.CurrentThread.Name)
'ProgressDownload.Value = Convert.ToInt32((downloadedBytes * 100) / totalBytesToDownload)
' downloadedBytesTextBox.Text = downloadedBytes.ToString("N", nfi)
Catch ex As Exception
Console.WriteLine("Error " + Thread.CurrentThread.Name)
Console.WriteLine(ex)
Finally
Console.WriteLine("Finally " + Thread.CurrentThread.Name)
GC.Collect()
' GC.WaitForPendingFinalizers()
'newThread.Abort()
'Try
'Thread.CurrentThread.Abort()
'Catch ex1 As Exception
'End Try
End Try
'Return 1
End Sub
公共子下载字节(ByVal p_fileValues作为fileValues)
将httpWebRequest设置为httpWebRequest
将httpWebResponse设置为httpWebResponse
暗淡的反应像溪流一样
Dim threadName=threadID
尝试
Console.WriteLine(“开始”+Thread.CurrentThread.Name)
httpWebRequest=DirectCast(WebRequest.Create(p_fileValues.URL),httpWebRequest)
'httpWebRequest.ProtocolVersion=HttpVersion.Version11
httpWebRequest.KeepAlive=False
httpWebRequest.AddRange(p_fileValues.StartPoint,p_fileValues.EndPoint)
httpWebRequest.Credentials=CredentialCache.DefaultCredentials
httpWebRequest.Proxy=WebRequest.DefaultWebProxy
httpWebResponse=CType(httpWebRequest.GetResponse(),httpWebResponse)
responseStream=httpWebResponse.GetResponseStream()
Dim bytesSize为整数=0
'用于存储和写入从服务器检索的数据的缓冲区
Dim downBuffer As Byte()=新字节(2047){}
Dim BytesalReadyDownload为Int64=p_fileValues.StartPoint
'循环通过缓冲区,直到缓冲区为空
While(True)
'单击中止按钮时结束循环
如果(isActionAborted=True),则
退出时
如果结束
'当前周期>总周期,然后在
如果(currentCycleDownload>cycleNumericUpDown.Value),则
退出时
如果结束
bytesSize=responseStream.Read(downBuffer,0,downBuffer.Length)
bytesAlreadyDownloaded+=ByteSize
'speedtimer.Start()
如果(通过细化p_fileValues.EndPoint),则
'Console.WriteLine(“下载部件文件退出”+p_fileValues.StartPoint.ToString()+”,“+p_fileValues.EndPoint.ToString())
退出时
如果结束
结束时
responseStream.Flush()
responseStream.Close()
httpWebResponse.Close()
responseStream.Dispose()
responseStream=无
httpWebResponse=无
Console.WriteLine(“End”+Thread.CurrentThread.Name)
'ProgressDownload.Value=Convert.ToInt32((downloadedBytes*100)/totalBytesToDownload)
'downloadedBytesTextBox.Text=downloadedBytes.ToString(“N”,nfi)
特例
Console.WriteLine(“错误”+Thread.CurrentThread.Name)
控制台写入线(ex)
最后
Console.WriteLine(“Finally”+Thread.CurrentThread.Name)
GC.Collect()
'GC.WaitForPendingFinalizers()
'newThread.Abort()
“试试看
'Thread.CurrentThread.Abort()
'捕获ex1作为异常
“结束尝试
结束尝试
'返回1
端接头
此功能将更新表单上的进度条和其他标签:
Private Sub UpdateDownloadProgress(ByVal BytesRead As Int64, ByVal TotalBytes As Int64)
If Not swDL Is Nothing AndAlso swDL.IsRunning Then
swDL.Stop()
If swDL.ElapsedMilliseconds > 0 Then
resultGrid.Rows.Item(HandoverGridCounter - 1).Cells(4).Value &= "DL: " & swDL.ElapsedMilliseconds & " ms"
End If
swDL = Nothing
End If
If (dlCurrentspeed > 0) Then
'txtCurrentSpeedDL.Text = Math.Round((dlCurrentspeed / 1024), 0) & " KB/s"
End If
downloadedBytes += BytesRead
If downloadedBytes >= totalBytesToDownload Then
downloadedBytes = totalBytesToDownload
End If
ProgressDownload.Value = Convert.ToInt32((downloadedBytes * 100) / TotalBytes)
downloadedBytesTextBox.Text = downloadedBytes.ToString("N", nfi) ' & " bytes"
If totalBytesToDownload = 0 Then
totalBytesToDownload = TotalBytes
txtBytesToDownload.Text = totalBytesToDownload.ToString("N", nfi)
End If
If downloadedBytes >= totalBytesToDownload Then
dlCurrentspeed = 0
dlStopWatch.Stop()
testEndTickDownload = My.Computer.Clock.TickCount
testDeltaDownload = (testEndTickDownload - testStartTickDownload) / 1000
If DLtimedOut = True Then
DownloadCompleted(TestStatus.Cancelled.ToString(), "")
Else
DownloadCompleted(TestStatus.Completed.ToString(), "")
End If
If currentCycleDownload <= cycleNumericUpDown.Value Then
If protocolComboBox.Text = "HTTP" Then
StartHttpDownload()
Else
StartFtpDownload()
End If
End If
End If
End Sub
Private Sub UpdateDownloadProgress(ByVal BytesRead为Int64,ByVal TotalBytes为Int64)
如果不是swDL什么都不是,也就是swDL.IsRunning,那么
swDL.Stop()
如果swDL.elapsedmillisons>0,则
resultGrid.Rows.Item(HandoverGridCounter-1).单元格(4).值&=“DL:”&swDL.elapsedmillesons&“ms”
如果结束
swDL=无
如果结束
如果(dlCurrentspeed>0),则
'txtCurrentSpeedDL.Text=Math.Round((dlCurrentspeed/1024),0)和'KB/s'
如果结束
downloadedBytes+=字节读取
如果downloadedBytes>=TotalByTestToDownload,则
downloadedBytes=TotalByTestToDownload
如果结束
ProgressDownload.Value=Convert.ToInt32((下载字节*100)/TotalBytes)
downloadedBytesTextBox.Text=downloadedBytes.ToString(“N”,nfi)&“bytes”
如果TotalByTestToDownload=0,则
TotalByTestToDownload=TotalBytes
txtBytesToDownload.Text=totalBytesToDownload.ToString(“N”,nfi)
如果结束
如果downloadedBytes>=TotalByTestToDownload,则
dlCurrentspeed=0