°Ë±¦Êé¿â > ÎÄѧÆäËûµç×ÓÊé > VB2008´ÓÈëÃŵ½¾«Í¨(PDF¸ñʽӢÎÄ°æ) >

µÚ100²¿·Ö

VB2008´ÓÈëÃŵ½¾«Í¨(PDF¸ñʽӢÎÄ°æ)-µÚ100²¿·Ö

С˵£º VB2008´ÓÈëÃŵ½¾«Í¨(PDF¸ñʽӢÎÄ°æ) ×ÖÊý£º ÿҳ4000×Ö

°´¼üÅÌÉÏ·½Ïò¼ü ¡û »ò ¡ú ¿É¿ìËÙÉÏÏ·­Ò³£¬°´¼üÅÌÉ쵀 Enter ¼ü¿É»Øµ½±¾ÊéĿ¼ҳ£¬°´¼üÅÌÉÏ·½Ïò¼ü ¡ü ¿É»Øµ½±¾Ò³¶¥²¿£¡
¡ª¡ª¡ª¡ªÎ´ÔĶÁÍꣿ¼ÓÈëÊéÇ©ÒѱãÏ´μÌÐøÔĶÁ£¡




¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡You¡¡need¡¡to¡¡instantiate¡¡a¡¡single¡¡ThreadedTask¡¡and¡¡associate¡¡it¡¡with¡¡a¡¡single¡¡Thread¡¡instance£»¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡like¡¡this£º¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡task1¡¡As¡¡ThreadedTask¡¡=¡¡New¡¡ThreadedTask£¨¡¨hello¡¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡task2¡¡As¡¡ThreadedTask¡¡=¡¡New¡¡ThreadedTask£¨¡¨goodbye¡¨£©¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread1¡¡As¡¡Thread¡¡=¡¡New¡¡Thread£¨AddressOf¡¡task1¡£MethodToRun£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread2¡¡As¡¡Thread¡¡=¡¡New¡¡Thread£¨AddressOf¡¡task2¡£MethodToRun£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread1¡£Start£¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread2¡£Start£¨£©¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡If¡¡you¡¡are¡¡running¡¡a¡¡stateful¡¡method£»¡¡you¡¡need¡¡to¡¡associate¡¡a¡¡task¡¡instance¡¡with¡¡a¡¡thread¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡instance¡£¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Using¡¡a¡¡Thread¡¡Parameter¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Suppose¡¡that¡¡you¡¡want¡¡to¡¡create¡¡a¡¡stateful¡¡thread¡£¡¡You¡¡can¡¡do¡¡this¡¡by¡¡using¡¡a¡¡thread¡¡parameter¡£¡¡In¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡other¡¡words£»¡¡the¡¡method¡¡that¡¡you¡¡invoke¡¡on¡¡another¡¡thread¡¡takes¡¡a¡¡parameter¡£¡¡Here¡¯s¡¡an¡¡example£º¡¡


¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­Page¡¡371¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡C¡¡HA¡¡P¡¡TE¡¡R¡¡¡¡¡¡1¡¡3¡¡¡¡¡¡¡ö¡¡¡¡¡¡¡¡L¡¡E¡¡AR¡¡N¡¡IN¡¡G¡¡¡¡¡¡AB¡¡O¡¡U¡¡T¡¡¡¡¡¡M¡¡U¡¡L¡¡T¡¡IT¡¡HR¡¡E¡¡AD¡¡IN¡¡G¡¡349¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Sub¡¡SimpleThreadWithStateTask£¨ByVal¡¡buffer¡¡As¡¡Object£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Console¡£WriteLine£¨¡¨You¡¡said¡¡£¨¡¨¡¡&¡¡buffer¡£ToString£¨£©¡¡&¡¡¡¨£©¡¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Sub¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Private¡¡Sub¡¡SimpleThreadWithState£¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread1¡¡As¡¡New¡¡Thread£¨AddressOf¡¡SimpleThreadWithStateTask£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread1¡£Start£¨¡¨my¡¡text¡¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Sub¡¡¡¡



¡¡¡¡¡¡¡¡¡¡The¡¡major¡¡difference¡¡with¡¡a¡¡thread¡¡parameter¡¡is¡¡that¡¡you¡¡declare¡¡the¡¡function¡¡that¡¡is¡¡executed¡¡¡¡

with¡¡a¡¡parameter£»¡¡and¡¡the¡¡¡¡Start£¨£©¡¡method¡¡has¡¡a¡¡parameter¡£¡¡¡¡

¡¡¡¡¡¡¡¡¡¡Two¡¡restrictions¡¡apply¡¡to¡¡using¡¡a¡¡thread¡¡parameter£º¡¡you¡¡can¡¡send¡¡only¡¡a¡¡single¡¡parameter£»¡¡¡¡

and¡¡that¡¡parameter¡¡must¡¡be¡¡an¡¡object¡£¡¡



Synchronizing¡¡Between¡¡Threads¡¡



When¡¡you¡¡have¡¡two¡¡threads¡¡and¡¡both¡¡share¡¡state¡¡£¨such¡¡as¡¡a¡¡variable£©£»¡¡a¡¡concurrency¡¡situation¡¡¡¡

may¡¡arise¡£¡¡Sharing¡¡state¡¡between¡¡two¡¡independent¡¡threads¡¡is¡¡not¡¡a¡¡problem¡¡if¡¡both¡¡threads¡¡¡¡

consider¡¡the¡¡data¡¡as¡¡read¡­only¡£¡¡What¡¡does¡¡the¡¡reading¡¡thread¡¡read£¿¡¡Is¡¡the¡¡state¡¡consistent£¿¡¡It¡¡is¡¡¡¡

probably¡¡not¡¡consistent£»¡¡and¡¡that¡¡is¡¡why¡¡you¡¡need¡¡to¡¡synchronize¡¡access¡¡to¡¡state¡£¡¡

¡¡¡¡¡¡¡¡¡¡Let¡¯s¡¡consider¡¡a¡¡simple¡¡¡¡collection¡¡class¡¡example¡£¡¡The¡¡following¡¡source¡¡code¡¡executes¡¡¡¡

in¡¡the¡¡calling¡¡thread£»¡¡instantiates¡¡a¡¡list¡¡collection£»¡¡and¡¡then¡¡adds¡¡two¡¡numbers¡¡to¡¡the¡¡collection¡£¡¡



Dim¡¡elements¡¡As¡¡List£¨Of¡¡Integer£©=¡¡New¡¡List£¨Of¡¡Integer£©£¨£©¡¡

elements¡£Add£¨10£©¡¡

elements¡£Add£¨20£©¡¡



¡¡¡¡¡¡¡¡¡¡In¡¡the¡¡next¡¡step£»¡¡we¡¡define¡¡a¡¡method¡¡that¡¡iterates¡¡the¡¡elements¡¡collection¡¡£¨which¡¡is¡¡declared¡¡at¡¡¡¡

a¡¡higher¡¡scope£©¡£¡¡



Sub¡¡Task1£¨£©¡¡

¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1000£©¡¡

¡¡¡¡¡¡¡¡Dim¡¡item¡¡As¡¡Integer¡¡

¡¡¡¡¡¡¡¡For¡¡Each¡¡item¡¡In¡¡elements¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Console¡£WriteLine£¨¡¨Item¡¡£¨¡¨¡¡&¡¡item¡¡&¡¡¡¨£©¡¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1000£©¡¡

¡¡¡¡¡¡¡¡Next¡¡

End¡¡Sub¡¡¡¡



¡¡¡¡¡¡¡¡¡¡This¡¡thread¡¡iterates¡¡the¡¡data£»¡¡and¡¡the¡¡two¡¡Thread¡£Sleep£¨£©¡¡calls¡¡put¡¡the¡¡threads¡¡to¡¡sleep¡¡for¡¡¡¡

1000¡¡milliseconds£»¡¡or¡¡1¡¡second¡£¡¡By¡¡putting¡¡the¡¡thread¡¡to¡¡sleep£»¡¡we¡¡can¡¡artificially¡¡construct¡¡a¡¡¡¡

situation¡¡where¡¡another¡¡thread¡¡adds¡¡to¡¡the¡¡collection¡¡while¡¡the¡¡collection¡¡is¡¡being¡¡iterated¡£¡¡¡¡

¡¡¡¡¡¡¡¡¡¡The¡¡method¡¡that¡¡adds¡¡an¡¡element¡¡to¡¡the¡¡collection¡¡is¡¡defined¡¡as¡¡follows£º¡¡



Sub¡¡Task2£¨£©¡¡

¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1500£©¡¡

¡¡¡¡¡¡¡¡elements¡£Add£¨30£©¡¡

End¡¡Sub¡¡


¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­Page¡¡372¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­

350¡¡¡¡¡¡¡¡¡¡¡¡¡¡CH¡¡AP¡¡T¡¡E¡¡R¡¡¡¡¡¡1¡¡3¡¡¡¡¡¡¡ö¡¡¡¡¡¡¡¡L¡¡E¡¡A¡¡R¡¡N¡¡I¡¡N¡¡G¡¡¡¡¡¡A¡¡B¡¡OU¡¡T¡¡¡¡¡¡M¡¡U¡¡L¡¡T¡¡I¡¡TH¡¡R¡¡E¡¡A¡¡DI¡¡N¡¡G¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡The¡¡Task1£¨£©¡¡and¡¡Task2£¨£©¡¡methods¡¡are¡¡started¡¡in¡¡separate¡¡threads¡¡as¡¡follows£º£º¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨10£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨20£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread1¡¡As¡¡New¡¡Thread£¨AddressOf¡¡Task1£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread2¡¡As¡¡New¡¡Thread£¨AddressOf¡¡Task2£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread1¡£Start£¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread2¡£Start£¨£©¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Running¡¡the¡¡threaded¡¡code¡¡will¡¡generate¡¡an¡¡exception£»¡¡but¡¡not¡¡immediately¡£¡¡First£»¡¡the¡¡caller¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread¡¡creates¡¡and¡¡starts¡¡thread1¡¡and¡¡thread2¡£¡¡thread1¡¡goes¡¡to¡¡sleep¡¡for¡¡1¡¡second£»¡¡and¡¡thread2¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡goes¡¡to¡¡sleep¡¡for¡¡1¡£5¡¡seconds¡£¡¡After¡¡thread1¡¡awakens£»¡¡one¡¡item¡¡in¡¡the¡¡collection¡¡is¡¡iterated£»¡¡and¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread1¡¡goes¡¡to¡¡sleep¡¡for¡¡another¡¡second¡£¡¡But¡¡before¡¡thread1¡¡reawakens£»¡¡thread2¡¡awakens¡¡and¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡adds¡¡an¡¡element¡¡to¡¡the¡¡collection¡£¡¡When¡¡thread1¡¡reawakens¡¡and¡¡attempts¡¡to¡¡iterate¡¡another¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡element¡¡in¡¡the¡¡collection£»¡¡an¡¡exception¡¡is¡¡generated£»¡¡as¡¡shown¡¡in¡¡Figure¡¡13¡­4¡£¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Figure¡¡13¡­4¡£¡¡Exception¡¡thrown¡¡after¡¡adding¡¡element¡¡to¡¡the¡¡collection£»¡¡as¡¡shown¡¡in¡¡the¡¡Visual¡¡Basic¡¡IDE¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡The¡¡InvalidOperationException¡¡is¡¡thrown¡¡to¡¡indicate¡¡that¡¡you¡¡can¡¯t¡¡add¡¡elements¡¡to¡¡a¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡collection¡¡while¡¡iterating¡¡a¡¡collection¡£¡¡The¡¡collection¡¡classes¡¡think¡¡it¡¡is¡¡a¡¡bad¡¡idea¡¡to¡¡modify¡¡and¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡iterate¡¡a¡¡collection¡¡at¡¡the¡¡same¡¡time¡£¡¡I¡¡agree¡¡with¡¡the¡¡collection¡¡classes£»¡¡because¡¡doing¡¡so¡¡could¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡give¡¡unpredictable¡¡results¡£¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡The¡¡problem¡¡in¡¡the¡¡source¡¡code¡¡is¡¡how¡¡to¡¡use¡¡the¡¡collection¡¡classes¡¡in¡¡a¡¡multithreaded¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡context¡£¡¡In¡¡the¡¡example£»¡¡items¡¡are¡¡added¡¡to¡¡the¡¡collection¡¡while¡¡the¡¡collection¡¡is¡¡being¡¡iterated¡£¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡A¡¡monly¡¡suggested¡¡approach¡¡is¡¡to¡¡use¡¡the¡¡type¡¡¡¡System¡£Collections¡£ObjectModel¡£¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ReadOnlyCollection£»¡¡as¡¡in¡¡the¡¡following¡¡example¡£¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Imports¡¡System¡£Collections¡£ObjectModel¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Imports¡¡System¡£Threading¡¡


¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­Page¡¡373¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡C¡¡HA¡¡P¡¡TE¡¡R¡¡¡¡¡¡1¡¡3¡¡¡¡¡¡¡ö¡¡¡¡¡¡¡¡L¡¡E¡¡AR¡¡N¡¡IN¡¡G¡¡¡¡¡¡AB¡¡O¡¡U¡¡T¡¡¡¡¡¡M¡¡U¡¡L¡¡T¡¡IT¡¡HR¡¡E¡¡AD¡¡IN¡¡G¡¡351¡¡



Module¡¡ThreadProblem¡¡

¡¡¡¡¡¡¡¡Dim¡¡elements¡¡As¡¡List£¨Of¡¡Integer£©¡¡=¡¡New¡¡List£¨Of¡¡Integer£©£¨£©¡¡



¡¡¡¡¡¡¡¡Sub¡¡Task1£¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1000£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡item¡¡As¡¡Integer¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡listElements¡¡As¡¡New¡¡ReadOnlyCollection£¨Of¡¡Integer£©£¨elements£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡For¡¡Each¡¡item¡¡In¡¡listElements¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Console¡£WriteLine£¨¡¨Item¡¡£¨¡¨¡¡&¡¡item¡¡&¡¡¡¨£©¡¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1000£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Next¡¡

¡¡¡¡¡¡¡¡End¡¡Sub¡¡



¡¡¡¡¡¡¡¡Sub¡¡Task2£¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1500£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨30£©¡¡

¡¡¡¡¡¡¡¡End¡¡Sub¡¡



¡¡¡¡¡¡¡¡Sub¡¡Main£¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨10£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨20£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread1¡¡As¡¡New¡¡Thread£¨AddressOf¡¡Task1£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread2¡¡As¡¡New¡¡Thread£¨AddressOf¡¡Task2£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread1¡£Start£¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread2¡£Start£¨£©¡¡

¡¡¡¡¡¡¡¡End¡¡Sub¡¡



End¡¡Module¡¡



¡¡¡¡¡¡¡¡¡¡The¡¡change¡¡is¡¡the¡¡bolded¡¡code£»¡¡which¡¡instantiates¡¡the¡¡type¡¡System¡£Collections¡£¡¡

ReadOnlyCollection£»¡¡to¡¡which¡¡we¡¡pass¡¡the¡¡elements¡¡list¡£¡¡The¡¡ReadOnlyCollection¡¡provides¡¡the¡¡¡¡

base¡¡class¡¡for¡¡a¡¡generic¡¡read¡­only¡¡collection¡£¡¡The¡¡For¡¡Each¡¡iterator¡¡then¡¡iterates¡¡a¡¡collection¡¡¡¡

that¡¡is¡¡read¡­only£»¡¡but¡¡based¡¡on¡¡the¡¡original¡¡collection¡£¡¡However£»¡¡running¡¡the¡¡code¡¡will¡¡result¡¡in¡¡¡¡

the¡¡same¡¡exception¡£¡¡This¡¡demonstrates¡¡that¡¡ReadOnlyCollection¡¡does¡¡not¡¡take¡¡a¡¡snapshot£»¡¡but¡¡¡¡

masks¡¡the¡¡collection¡£¡¡The¡¡mask¡¡disables¡¡the¡¡addition¡¡of¡¡items¡¡to¡¡the¡¡collection£»¡¡but¡¡because¡¡the¡¡¡¡

other¡¡thread¡¡is¡¡taking¡¡a¡¡shortcut¡¡and¡¡editing¡¡the¡¡original¡¡collection£»¡¡the¡¡read¡­only¡¡collection¡¡is¡¡¡¡

modified¡¡as¡¡well¡£¡¡¡¡

¡¡¡¡¡¡¡¡¡¡Let¡¯s¡¡say¡¡that¡¡converting¡¡the¡¡collection¡¡into¡¡a¡¡read¡­only¡¡collection¡¡had¡¡worked¡£¡¡It¡¡would¡¡¡¡

not¡¡have¡¡solved¡¡anything¡£¡¡A¡¡read¡­only¡¡collection¡¡means¡¡that¡¡the¡¡second¡¡thread¡¡would¡¡generate¡¡¡¡

an¡¡exception¡¡because¡¡you¡¡can¡¯t¡¡add¡¡elements¡¡to¡¡a¡¡collection¡¡that¡¡is¡¡read¡­only¡£¡¡The¡¡point¡¡is¡¡that¡¡¡¡

when¡¡writing¡¡multithreaded¡¡code¡¡that¡¡shares¡¡variables£»¡¡you¡¡don¡¯t¡¡have¡¡an¡¡easy¡¡solution£»¡¡because¡¡¡¡

you¡¡are¡¡trying¡¡to¡¡solve¡¡the¡¡problem¡¡of¡¡how¡¡to¡¡keep¡¡multiple¡¡cooks¡¡productive¡¡in¡¡a¡¡single¡¡kitchen¡£¡¡

¡¡¡¡¡¡¡¡¡¡We¡¡are¡¡trying¡¡to¡¡solve¡¡a¡¡classic¡¡reader/writer¡¡problem£»¡¡where¡¡some¡¡threads¡¡are¡¡interested¡¡¡¡

only¡¡in¡¡reading¡¡the¡¡data£»¡¡and¡¡other¡¡threads¡¡are¡¡interested¡¡only¡¡in¡¡modifying¡¡the¡¡data¡£¡¡One¡¡way¡¡¡¡

to¡¡synchronize¡¡the¡¡readers¡¡and¡¡writers¡¡is¡¡to¡¡use¡¡an¡¡exclusive¡¡lock£»¡¡so¡¡that¡¡only¡¡one¡¡thread¡¡may¡¡¡¡

read¡¡or¡¡write¡£¡¡


¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­Page¡¡374¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­¡­

352¡¡¡¡¡¡¡¡¡¡¡¡¡¡CH¡¡AP¡¡T¡¡E¡¡R¡¡¡¡¡¡1¡¡3¡¡¡¡¡¡¡ö¡¡¡¡¡¡¡¡L¡¡E¡¡A¡¡R¡¡N¡¡I¡¡N¡¡G¡¡¡¡¡¡A¡¡B¡¡OU¡¡T¡¡¡¡¡¡M¡¡U¡¡L¡¡T¡¡I¡¡TH¡¡R¡¡E¡¡A¡¡DI¡¡N¡¡G¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Using¡¡Exclusive¡¡Locks¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡When¡¡using¡¡exclusive¡¡locks¡¡in¡¡£»¡¡you¡¡are¡¡saying£»¡¡¡°Only¡¡one¡¡thread¡¡may¡¡execute¡¡this¡¡piece¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡of¡¡code¡£¡±¡¡If¡¡two¡¡threads¡¡want¡¡to¡¡execute¡¡a¡¡particular¡¡piece¡¡of¡¡code£»¡¡one¡¡will¡¡be¡¡granted¡¡access£»¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡while¡¡the¡¡other¡¡thread¡¡waits¡¡until¡¡the¡¡granted¡¡thread¡¡has¡¡exited¡¡the¡¡code¡¡block¡£¡¡It¡¡is¡¡important¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡to¡¡understand¡¡that¡¡an¡¡exclusive¡¡lock¡¡grants¡¡access¡¡to¡¡code£»¡¡not¡¡data£»¡¡but¡¡that¡¡code¡¡could¡¡access¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡data¡£¡¡And¡¡because¡¡only¡¡one¡¡thread¡¡is¡¡accessing¡¡the¡¡code£»¡¡it¡¡is¡¡implied¡¡that¡¡only¡¡one¡¡thread¡¡can¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡access¡¡the¡¡data¡£¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡The¡¡following¡¡is¡¡an¡¡example¡¡of¡¡code¡¡that¡¡uses¡¡exclusive¡¡locks¡£¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡£¡¡¡£¡¡¡£¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Module¡¡ThreadProblem¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡elements¡¡As¡¡List£¨Of¡¡Integer£©¡¡=¡¡New¡¡List£¨Of¡¡Integer£©£¨£©¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Sub¡¡Task1£¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1000£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡SyncLock¡¡elements¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡item¡¡As¡¡Integer¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡For¡¡Each¡¡item¡¡In¡¡elements¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Console¡£WriteLine£¨¡¨Item¡¡£¨¡¨¡¡&¡¡item¡¡&¡¡¡¨£©¡¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1000£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Next¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡SyncLock¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Sub¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Sub¡¡Task2£¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Thread¡£Sleep£¨1500£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡SyncLock¡¡elements¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨30£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡SyncLock¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Sub¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Sub¡¡Main£¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨10£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡elements¡£Add£¨20£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread1¡¡As¡¡New¡¡Thread£¨AddressOf¡¡Task1£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡thread2¡¡As¡¡New¡¡Thread£¨AddressOf¡¡Task2£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread1¡£Start£¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡thread2¡£Start£¨£©¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Sub¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Module¡¡



¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡The¡¡bolded¡¡lines¡¡use¡¡the¡¡SyncLock¡¡and¡¡End¡¡SyncLock¡¡keywords£»¡¡which¡¡represent¡¡a¡¡code¡¡block¡¡of¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡exclusive¡¡access¡£¡¡The¡¡thread¡¡is¡¡granted¡¡access¡¡to¡¡only¡¡a¡¡single¡¡code¡¡block¡¡in¡¡each¡¡instance¡£¡¡¡¡

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Looking¡¡at¡¡the¡¡code¡¡within¡¡the¡¡block£»¡¡you¡¡can¡¡see¡¡that¡¡the¡¡collection¡¡

·µ»ØĿ¼ ÉÏÒ»Ò³ ÏÂÒ»Ò³ »Øµ½¶¥²¿ ÔÞ£¨0£© ²È£¨1£©

Äã¿ÉÄÜϲ»¶µÄ