青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Prayer

在一般中尋求卓越
posts - 1256, comments - 190, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

在vb.net中運用多線程實現遠程數據收集

Posted on 2008-12-11 16:09 Prayer 閱讀(3013) 評論(1)  編輯 收藏 引用 所屬分類: SOCKET

作者:楊泉波

引言

    在筆者參與的四川省重點污染源企業環境遠程監控系統中,有一項非常重要的工作:將多達80臺的遠程DVS(視頻服務器)的監測數據通過因特網傳輸,由上位機收集上來,寫入SQL Server 2005數據庫中。遠程數據每隔一分鐘發送一次實時數據。如果數據在一分鐘內傳送不成功,那么DVS將認為網絡已經斷開,又要不斷的發起新的連接。因此,上位機能不能及時的準確的收集、寫入,是系統成敗的關鍵。

項目分析

    80多臺遠程DVS正在不間斷的采集數據,在網絡正常的情況下,會不間斷的向上位機發送數據。如果采用傳統的單線程結構,上位機接受連接請求,接收處理數據,將數據寫入數據庫,然后再接受新的連接請求,接收處理數據,……,這樣,上位機程序異常繁忙,CPU利用率幾乎將達100%。由于服務器不能迅速處理請求,DVS只好等待。
    更為重要的是,為了減少上位機發送響應連接的次數,設備采用的是長連接,即發送一次連接請求并得到響應后,發送數據時不再發送連接請求。因此,要求上位機能夠保存客戶端的Socket。
為了避免這種情形發生。筆者采用了異步、多線程來處理。所謂異步,是程序調用一個方法后立即返回,總體而言,主線程與方法線程并行執行。而同步即程序執行一個方法,等該方法返回之后,繼續往下走,本系統從功能上分成3個模塊,即3個前后關聯的線程:主線程、數據接收線程、存入數據庫線程,它們異步執行。

主線程

    主線程工作流程如圖一所示。其主要功能是:初始化參數,如連接端口號、IP地址等,偵聽連接請求,將傳入的連接保留到TcpClient對象數組sockets,而這個數組sockets恰恰是我們后面線程中要用到的全局變量。 為了不使線程間爭用這個數組變量,這里用到了VB.net提供的Monitor類,它提供同步對象的訪問的機制。
    當主線程偵聽到遠程DVS有連接請求時,立即執行AcceptTcpClient方法,創建一個TcpClient實例,并將它放入sockets數組。同時創建線程對象serverthread。
聲明創建線程時,使用 ThreadStart 委托作為其唯一參數的構造函數創建 Thread 類的新實例,創建線程時需要傳遞處理連接的過程或函數的地址以被線程調用。創建線程委托,傳遞需要操作的過程的地址,這部分的代碼如下所示:
Public Sub WaitData()
        Try
            Dim ipHostInfo As IPHostEntry = Dns.Resolve(Dns.GetHostName())
            Dim localAddr As IPAddress = ipHostInfo.AddressList(0)
            s = New TcpListener(localAddr, ListenPort)
            s.Start()’開始偵聽連接請求
            Dim Recdatathread As New Thread(New ThreadStart(AddressOf RecDataProc)) ’創建數據接收線程
            Recdatathread.IsBackground = True
            Recdatathread.Start()’啟動線程
            While True
                Dim client As TcpClient = s.AcceptTcpClient()
                Monitor.Enter(sockets) '在指定對象上獲取排他鎖
                sockets(socketcount) = client
                socketcount = socketcount + 1
                Monitor.Exit(sockets) '釋放指定對象上的排他鎖                 
            End While
        Catch e As SocketException
            s.Stop()
            saveErrLog(Date.Now, CType(s.AcceptTcpClient.Client.RemoteEndPoint, IPEndPoint).Address.ToString(), e.Message)’寫入錯誤日志
        Catch e As ThreadAbortException
            t.Abort()
            saveErrLog(Date.Now, CType(s.AcceptTcpClient.Client.RemoteEndPoint, IPEndPoint).Address.ToString(), e.Message) ’寫入錯誤日志
        Finally
            t.Abort()
            End
        End Try
End Sub

數據接收線程

    數據接收線程的工作流程如圖二所示。主要功能是:將掛起連接的DVS上傳數據從流中讀取出來,創建數據寫入線程,并在listbox中顯示。
從保存的socket數組中讀取字節流時,必須考慮以下問題:
一、有些DVS可能會在工作一段時間后發生設備故障或者網絡中斷,但服務器保存的是其歷史socket,因此,必須判斷其connect屬性,即設備是否在線。
二、為了減少服務器的空等時間,必須判斷流對象(stream)的DataAvailable屬性。
三、創建線程saveToDb時,必須考慮傳入參數的問題。通常的線程創建是不可提供參數的。我們將線程saveToDb的執行體封裝到一個類中,通過初始化類的成員變量的方法,來達到傳送參數的目的。
四、由于本線程是長駐內存并循環執行的。因此,應當在適當的地方阻止,否則,CPU的利用率將達幾乎100%。
這部分的代碼如下:
Public Sub RecDataProc()
        Dim i As Integer
        Dim c As TcpClient
        While (True)
            Try
                For i = 0 To socketList.Count - 1
          If socketList.Item(i).client.connected Then '如果該連接在線
             Dim dh1 As DelegateHandler = New DelegateHandler(AddressOf displayStatusBarPanel2)
'New 出一個委托并指定委托方法
                      Me.Invoke(dh1, New Object() {CStr(i)})  '調用invoke方法
                      c = socketList.Item(i)
                      Dim stream As NetworkStream = c.GetStream()
                      If stream.DataAvailable Then
                      Dim dh As DelegateHandler1 = New DelegateHandler1(AddressOf ShowInBox)
                      Dim readbuff As New ReadBuffClass(c, stream, Connection, dh) '由構造函數來初始化成員變量
                      ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf readbuff.ReadBuff), readbuff)’把具體從流中讀取數據的工作交給線程池的線程來進行
                       Dim workerThreads, portThreads As Integer
                       ThreadPool.GetAvailableThreads(workerThreads, portThreads)
                       Dim dh2 As DelegateHandler = New DelegateHandler(AddressOf displayStatusBarPanel4)
'New 出一個委托并指定委托方法
                       Me.Invoke(dh2, New Object() {workerThreads.ToString})  '調用invoke方法
                    End If
                       Thread.Sleep(20) '如果不阻止,則CPU利用率將為100%
                    End If
                Next
             Catch ex As System.ArgumentOutOfRangeException
             Catch ex As System.InvalidOperationException
             Catch ex As ObjectDisposedException 'TcpClient 已關閉
             Catch ex As SocketException
             Catch ex As ThreadAbortException
             Catch ex As System.IO.IOException              
             Catch ex As System.AccessViolationException
             Finally
            End Try
        End While
End Sub

數據處理線程

    這部份線程每個都由線程池來調度運行。由于要接收線程參數,因此,線程本身被封裝到一個類中,限于篇幅的原因,只描述類的結構。
Public Class ReadBuffClass
    Private sck As TcpClient
    Private ns As NetworkStream
    Private sqlcnn As SqlConnection
    Private delg As frmServerMain.DelegateHandler1
 
    Dim sqlcmd As SqlCommand
Dim sqlda As SqlDataAdapter
 
Public Sub New(ByVal sc As TcpClient, ByVal n As NetworkStream, ByVal cn As SqlConnection, ByVal dh As frmServerMain.DelegateHandler1) '由構造函數來初始化成員變量
        Me.sck = sc
        Me.ns = n
        Me.sqlcnn = cn
       Me.delg = dh
End Sub
 
Public Sub ReadBuff(ByVal state As Object) ' 線程的入口函數
        Dim datastring As String = ""
        ns.ReadTimeout = 100 '讀取失敗前經歷的毫秒數
        Try
            While (True)
                Dim bytes(2048) As Byte
                ns.Read(bytes, 0, 2048)
                datastring = datastring + Encoding.ASCII.GetString(bytes)
                If datastring.IndexOf(vbCrLf) > 0 Then
                    Exit While
                End If
            End While
            delg.Invoke(datastring, sck) '通過委托的方式,將參數傳給UI
            Dim tmparr() As String = datastring.Split("##")
            Dim i As Integer
            For i = 0 To tmparr.Length - 1
                If tmparr(i) <> "" Then
                    ProcessInfo(tmparr(i))
                End If
            Next
        Catch ex As System.AccessViolationException
        Catch ex As NotSupportedException
       Catch ex As ArgumentNullException
       Catch ex As ArgumentOutOfRangeException
       Catch ex As ObjectDisposedException
Catch ex As IO.IOException '
       Catch ex As SocketException
       Catch ex As ThreadAbortException
      Finally
   End Try
End Sub
 
Private Sub ProcessInfo(ByVal tmpString As String) '對收到的數據進行解析、處理
……
End Sub
……
End Class

結束語

    本文著重論述的是在VB2005的環境下,運用多線程異步實現遠程DVS數據收集的原理,重點考慮的是怎樣提高程序的反應速度,特別討論了程序開發中的一些細節問題,對有志于從事遠程臨控系統開發的軟件人員有一定的參考意義。
文中代碼在windows2003+VB2005+SqlServer2005的環境下調試通過,現在正在使用。

Feedback

# re: 在vb.net中運用多線程實現遠程數據收集  回復  更多評論   

2009-05-11 17:11 by anndy
看來博主是socket方面的編程的專家了,請問下“在vb.net中運用多線程實現遠程數據收集”,是你的原創嗎
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            一区二区三区日韩在线观看| 一本久道久久久| 欧美三级在线| 亚洲精一区二区三区| 亚洲蜜桃精久久久久久久| 欧美日韩精品免费| 亚洲国产精品成人| 韩国成人精品a∨在线观看| 亚洲精品国产精品久久清纯直播 | 亚洲六月丁香色婷婷综合久久| 久久综合九色综合欧美狠狠| 一区二区三区在线看| 久久久精品日韩欧美| 久久久av毛片精品| 中文av字幕一区| 亚洲国产精品一区制服丝袜| 好吊成人免视频| 国产在线观看精品一区二区三区 | 99国产精品久久久| 91久久综合| 亚洲一区欧美二区| 性刺激综合网| 亚洲精品美女91| 国产精品久久国产愉拍 | 麻豆久久婷婷| 女同一区二区| 欧美一区二区视频在线观看| 亚洲福利在线看| 欧美日韩免费看| 国产精品久久97| 亚洲精品之草原avav久久| 在线综合亚洲欧美在线视频| 快射av在线播放一区| 亚洲一区二区高清| 欧美一区二区三区免费看| 国产午夜精品理论片a级大结局| 亚洲国产精品精华液2区45| 久久国产精品亚洲va麻豆| 亚洲精品裸体| 欧美激情一区二区三区全黄| 国产欧美日韩视频在线观看 | 欧美一区二区精品在线| 欧美日本在线播放| 亚洲一级在线| 亚洲欧美欧美一区二区三区| 欧美激情按摩| 亚洲片区在线| 欧美1区视频| 欧美日韩亚洲天堂| 欧美在线观看视频| 蜜臀a∨国产成人精品| 亚洲欧美日韩中文视频| 久久躁日日躁aaaaxxxx| 亚洲一区二区欧美| 久久久精品网| 亚洲亚洲精品在线观看| 欧美一二三区在线观看| 亚洲国产一区二区三区在线播| 亚洲精选在线观看| 国产一区在线观看视频| 最新中文字幕亚洲| 国产精品系列在线| 99精品欧美一区| 日韩亚洲欧美精品| 久久黄金**| 午夜精品影院| 欧美三级午夜理伦三级中视频| 午夜视频一区二区| 亚洲午夜精品视频| 国产亚洲一区二区三区在线观看| 欧美一区二区私人影院日本 | 国产精品视频最多的网站| 亚洲成人资源| 亚洲欧洲精品一区二区三区波多野1战4 | 一本久久青青| 亚洲手机视频| 欧美性做爰猛烈叫床潮| 亚洲午夜高清视频| 欧美一区免费视频| 亚洲国产精品福利| 欧美国产1区2区| 一本色道久久加勒比精品| 午夜精品久久一牛影视| 一区一区视频| 欧美私人网站| 久久久午夜电影| 一区二区三区欧美在线| 久久av老司机精品网站导航| 激情亚洲一区二区三区四区| 免费欧美日韩| 午夜国产精品视频| 亚洲三级免费电影| 久久久水蜜桃av免费网站| 99国内精品久久| 狠狠入ady亚洲精品| 久久久www成人免费精品| 国产精品扒开腿做爽爽爽软件| 99国产精品国产精品久久| 玖玖在线精品| 亚洲制服少妇| 一本综合久久| 在线精品亚洲一区二区| 国产精品一区二区三区久久| 老鸭窝毛片一区二区三区| 午夜日韩电影| 亚洲午夜精品网| 亚洲最新视频在线| 亚洲国产精品一区二区www在线 | 欧美一级黄色网| 99热这里只有精品8| 1769国内精品视频在线播放| 国产情人节一区| 好吊一区二区三区| 国产亚洲欧美日韩美女| 国产亚洲一区在线播放| 激情综合五月天| 亚洲国产精品福利| 欧美一区二区三区日韩视频| 韩国三级电影久久久久久| 欧美高清视频免费观看| 欧美精品久久一区二区| 欧美电影电视剧在线观看| 老鸭窝91久久精品色噜噜导演| 99re66热这里只有精品3直播| 一本一本久久| 亚洲欧美日韩在线综合| 中文一区二区| 欧美日韩国产精品一区| 国产精品久久久久999| 精品1区2区3区4区| 亚洲免费在线| 亚洲一区二区三区高清不卡| 欧美韩日一区二区| 999亚洲国产精| 欧美激情亚洲| 亚洲日韩欧美视频| 午夜在线精品偷拍| 欧美激情第3页| 亚洲大胆人体在线| 亚洲综合色网站| 亚洲免费在线视频| 欧美 日韩 国产在线| 一区二区三区日韩欧美| 欧美激情视频在线免费观看 欧美视频免费一 | 99香蕉国产精品偷在线观看| 欧美一区网站| 国产精品区二区三区日本| 亚洲视频日本| 中文精品视频| 国产主播精品在线| 欧美高清不卡| 国产精品每日更新| 久久久www成人免费无遮挡大片| 99riav久久精品riav| 欧美视频在线播放| 性亚洲最疯狂xxxx高清| 久久久亚洲精品一区二区三区| 有码中文亚洲精品| 亚洲免费观看| 欧美精品电影| 亚洲免费伊人电影在线观看av| 午夜在线精品偷拍| 中文国产一区| 欧美黄色免费网站| 久久国产精品99国产精| 国产精品国产三级欧美二区| 在线观看av一区| 欧美激情性爽国产精品17p| 国产一区日韩一区| 日韩视频在线一区| 亚洲人成小说网站色在线| 一区二区不卡在线视频 午夜欧美不卡在 | 欧美在线视频导航| 欧美激情第1页| 亚洲欧洲日本国产| 亚洲高清在线观看一区| 久久久国产午夜精品| 久久综合色88| 亚洲电影网站| 欧美a级理论片| 亚洲动漫精品| 欧美激情第五页| 欧美午夜免费| 亚洲欧美成人综合| 最近中文字幕mv在线一区二区三区四区 | 欧美在现视频| 美国三级日本三级久久99| 欧美丰满少妇xxxbbb| 亚洲影院在线| 免费欧美日韩| 欧美成人四级电影| 欧美一激情一区二区三区| 这里只有精品视频在线| 日韩一级精品| 欧美日韩xxxxx| 欧美日产一区二区三区在线观看| 久久亚洲国产成人| 亚洲免费视频观看| 亚洲欧美日本国产专区一区| 精品成人一区二区三区|