乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Delphi多線程下的ADO編程

       獨(dú)孤求財(cái) 2012-03-20

      Delphi多線程下的ADO編程

      時(shí)間:2011-5-27來(lái)源:yang 作者: peng點(diǎn)擊: 134次

      Delphi多線程下的ADO編程

       

       

      前言:

      幾個(gè)月前接到一個(gè)任務(wù):將一后臺(tái)程序訪問(wèn)數(shù)據(jù)庫(kù)的方式從BDE改為ADO,原因是由于業(yè)務(wù)量的增加,通過(guò)BDE不論是向數(shù)據(jù)庫(kù)寫入數(shù)據(jù)還是從數(shù)據(jù)庫(kù)中讀出數(shù)據(jù)的速度都變得無(wú)法忍受,大家都知道ADO在數(shù)據(jù)庫(kù)訪問(wèn)速度方面比BDE要快的多了(我寫了一個(gè)測(cè)試程序使用ADO比使用BDE快了近100倍!)。這個(gè)任務(wù)還不簡(jiǎn)單嘛,只要將BDE的控件更換成ADO的再修改一些代碼不就搞定了!我當(dāng)時(shí)確實(shí)是這么想的,而且用了不到一個(gè)小時(shí)就搞定,測(cè)試運(yùn)行一段沒(méi)問(wèn)題,大功告成了,我想。誰(shuí)知道一個(gè)惡夢(mèng)就此開(kāi)始,我的愚昧無(wú)知使我在程序中埋下了一個(gè)超級(jí)炸彈,它的威力不次于9.11撞擊世貿(mào)大廈的兩架客機(jī),整個(gè)系統(tǒng)被它無(wú)情的催跨。程序在運(yùn)行很長(zhǎng)一段時(shí)間候捕獲到一系列的異常:

      OLE error 800A0E7F

      Access violation at address 00135770. Write of address 005D8B78

      Access violation at address 00178EC6. Read of address FFFFFFFF

      Access violation at address 1F499BDD in module ‘msado15.dll‘. Read of address 0000000C

      …….

      接下來(lái)我們的系統(tǒng)就像世貿(mào)大廈一下悲壯的倒下了。

       

      為什么?

             為什么?程序在為改動(dòng)之前使用BDE運(yùn)行得好好的,我并沒(méi)有更改程序的結(jié)構(gòu)啊?我十分的迷惑,當(dāng)然要想解決問(wèn)題一切都得從錯(cuò)誤代碼開(kāi)始。

         OLE error 800A0E7F:什么咚咚來(lái)的?它什么意思?什么原因引起的?我找了半天也沒(méi)有在我的系統(tǒng)里找到它的說(shuō)明,好在現(xiàn)在網(wǎng)絡(luò)發(fā)達(dá),也許有人遇到跟我一樣的問(wèn)題吧,于是我用OLE error 800A0E7F作為關(guān)鍵字搜了一下,嘿嘿,果真被我找到了:

      >0x800A0E7F Operation cannot be performed while executing
      > asynchronously.

      異步執(zhí)行時(shí)操作不能被執(zhí)行(完成),還是不太清楚錯(cuò)誤的原因,于是我在一個(gè)網(wǎng)站發(fā)布了帖子求助,一些人告訴我ADO線程不安全,需要線程同步,事實(shí)上我的程序做了同步,而且針對(duì)不同的應(yīng)用使用了多個(gè)ADOConnection,我想我應(yīng)該自己動(dòng)手來(lái)好好研究一下這個(gè)問(wèn)題了,它很意思。接下來(lái)我該好好分析我的程序并做一系列的測(cè)試來(lái)找到那個(gè)炸彈。

       

      找出炸彈

       

          在我的程序里所有訪問(wèn)數(shù)據(jù)庫(kù)都是通過(guò)一個(gè)DataModule單元TDataModule1類提供的接口來(lái)完成,共有三個(gè)線程使用到了TDataModule1的對(duì)象DataModule1,DataModule1是一全局變量,下面是數(shù)據(jù)庫(kù)的訪問(wèn)模式的結(jié)構(gòu)模型圖。(實(shí)際結(jié)構(gòu)要復(fù)雜很多)

       

       


      數(shù)據(jù)庫(kù):
      ADOConnection1
      ADOConnection2
      Table1
      Table2
      ①ADOQuery1
      ②ADOQuery3
      ①ADOProcedure1
      ①ADOProcedure2
      ①UpdateQuery
      ③ADOQuery2
       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       

       



      圖1

      說(shuō)明:


      ①UpdateQuery
       



                         ADOQuery控件用來(lái)修改table2記錄,①代表為線程1所有,

      白色代表使用頻率很低(顏色越深說(shuō)明使用頻率越高)

       


      ③ADOQuery2
       



                         查詢table2,③代表為線程3所有,使用頻率較高

       


      ②ADOQuery3
       



                         查詢table2,③代表為線程2所有,使用頻率很高

       


      ①ADOProcedure1
                 

                            ADO存儲(chǔ)過(guò)程控件向表table2插入數(shù)據(jù),屬于線程1頻繁使用

       


      ①ADOProcedure2
       



      修改ADOProcedure1插入的記錄,屬于線程1頻繁使用

       

      其中線程3和線程2使用ADO控件時(shí)沒(méi)有加鎖,而線程1的所有訪問(wèn)都加鎖了(這樣做毫無(wú)作用)

       

      程序的結(jié)構(gòu)出來(lái)了,問(wèn)題在哪里呢?接下來(lái)我寫了一個(gè)小小的測(cè)試程序,該程序的結(jié)構(gòu)與上面相同,它擁有三個(gè)線程和一個(gè)DataMoule單元,線程一通過(guò)ADOQuery1查詢數(shù)據(jù)庫(kù)DBTest的table1的記錄,線程二通過(guò)ADOQuery2向table1中插入記錄,線程三通過(guò)ADOQuery3修改table1中最后一條記錄的某個(gè)字段。ADOQuery1、ADOQuery2、ADOQuery3都通過(guò)ADOConnection1與數(shù)據(jù)庫(kù)DBTest1建立連接,一開(kāi)始,所有的線程都不做同步,運(yùn)行,OK!錯(cuò)誤出來(lái)了其中兩個(gè)錯(cuò)誤正是我所想要的,這就是我的程序報(bào)的錯(cuò)啊。

       


      圖二

       

      接下來(lái)我將三個(gè)ADOQuery都加上鎖,再運(yùn)行沒(méi)問(wèn)題,我又將ADOQuery分別通過(guò)三個(gè)不同的ADOConnection來(lái)連接數(shù)據(jù)庫(kù)且不加鎖也沒(méi)有問(wèn)題??磥?lái)我是找到那個(gè)可惡的炸彈了,怎么拆了它?

       

      排除炸彈

       

      炸彈找到了,我該怎么拆它?是簡(jiǎn)單的做線程同步還是每個(gè)線程都是用一個(gè)ADOConnection?這下我再也不敢蠻干了,我得好好看看這方面的資料,在Delphi幫助文檔,《Using the main VCL thread》我找到了下面一段話:

      ……

      Data access components are thread-safe as long as each thread has its own database session component. The one exception to this is when you are using Access drivers. Access drivers are built using the Microsoft ADO library, which is not thread-safe.

      …..

      同樣在Delphi的幫助文檔《Managing multiple sessions》中給我明確的建議:

      ……

      If you create a single application that uses multiple threads to perform database operations, you must create one additional session for each thread.

      …..

      喔找到了:ADO控件是線程不安全的,所以如果你的程序是使用多線程訪問(wèn)數(shù)據(jù)庫(kù)的話你應(yīng)該確保每個(gè)線程都有自己的會(huì)話。

      事實(shí)上在另外一本書《Delphi 4編程技術(shù)內(nèi)幕》一書在談到線程安全數(shù)據(jù)庫(kù)訪問(wèn)也有相同的建議,不過(guò)臺(tái)灣李維先生在他的《Delphi 5.X ADO/MTS/COM+高級(jí)程序設(shè)計(jì)篇》卻說(shuō),如果你的程序不是連接多個(gè)數(shù)據(jù)庫(kù)的話,最好同一數(shù)據(jù)庫(kù)使用一個(gè)連接,不要使用多個(gè)連接。怎么辦?誰(shuí)對(duì)誰(shuí)錯(cuò)?為什么要使用一個(gè)連接呢?這主要是從服務(wù)器來(lái)考慮,因?yàn)閿?shù)據(jù)庫(kù)服務(wù)器需要為每個(gè)連接分配一定的資源并對(duì)其進(jìn)行維護(hù),連接數(shù)越多服務(wù)器方所耗的資源就越多,服務(wù)器的性能也就越差,所以要盡可能的減少客戶端的連接數(shù)。好在我的程序是作為服務(wù)器程序增加一些連接對(duì)數(shù)據(jù)庫(kù)服務(wù)器的影響不會(huì)很大,現(xiàn)在我可以重新設(shè)置我的數(shù)據(jù)庫(kù)訪問(wèn)結(jié)構(gòu)模型了

       


      數(shù)據(jù)庫(kù):
      ADOConnection1
      ADOConnection2
      Table1
      Table2
      ①ADOQuery1
      ②ADOQuery3
      ①ADOProcedure1
      ①ADOProcedure2
      ①UpdateQuery
      ③ADOQuery2
      ADOConnection2
       

       

       

       

       

       



                                                                                     

       

       

       

       

       

       

       

       

       

       

       

       

      圖三

       

      我增加了一個(gè)ADOConnection以保證每個(gè)線程都有一個(gè)自己連接(會(huì)話),從而避免出現(xiàn)資源沖突,我的問(wèn)題是不是解決了呢?是的,這個(gè)問(wèn)題已經(jīng)解決了,將我的程序與數(shù)據(jù)庫(kù)放在同一臺(tái)機(jī)器上運(yùn)行沒(méi)有問(wèn)題,但是當(dāng)程序與數(shù)據(jù)庫(kù)服務(wù)器不在同一臺(tái)機(jī)器上運(yùn)行時(shí)會(huì)出現(xiàn)一個(gè)新的問(wèn)題。

       

      [DBNMPNTW]ConnectionWrite(writeFile())錯(cuò)誤

           這個(gè)錯(cuò)誤不是多線程引起的,而是Micrsoft自己的一個(gè)問(wèn)題,產(chǎn)生該問(wèn)題的原因可能是因?yàn)榫W(wǎng)絡(luò)異常而引起的,可以通過(guò)SQLServer客戶端的默認(rèn)的網(wǎng)絡(luò)協(xié)議named pipes network propocol 改為 TCP/IP Sockets,具體做法請(qǐng)參考Micrsoft技術(shù)支持網(wǎng)站的《Microsoft Knowledge Base Article - Q178040》

       

      總結(jié)

         由于ADO控件的線程不安全性(事實(shí)上這種不安全性是來(lái)自Micrsoft ADO Library,所以在其它開(kāi)發(fā)工具中也存在同樣的問(wèn)題)因此在使用多線程ADO編程時(shí)應(yīng)該注意一下問(wèn)題:

       

      第一:要保證每個(gè)線程都擁有自己的會(huì)話。

      第二:作為客戶端程序應(yīng)該盡可能的減少與數(shù)據(jù)庫(kù)庫(kù)服務(wù)器的連接數(shù)。

      第三:在退出線程之前確保釋放所有的資源。

       

      參考文獻(xiàn):

      1、李維《Delphi 5.X ADO/MTS/COM+高級(jí)程序設(shè)計(jì)篇》 機(jī)械工業(yè)出版社 2000。

      2、Charlie Calvert《Delphi 4編程技術(shù)內(nèi)幕》瀟湘工作室 譯 機(jī)械工業(yè)出版社 1999。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多