2010-04-02 11 views
9

बहु-थ्रेडेड कॉल का निम्न पैटर्न .NET FileStream पर स्वीकार्य है?फ़ाइलस्ट्रीम के लिए सिंक्रनाइज़ेशन आवश्यकताएं (प्रारंभ/समाप्ति) (पढ़ें/लिखें)

कई इस तरह की एक विधि बुला धागे:

ulong offset = whatever; // different for each thread 
byte[] buffer = new byte[8192]; 
object state = someState; // unique for each call, hence also for each thread 

lock(theFile) 
{ 
    theFile.Seek(whatever, SeekOrigin.Begin); 
    IAsyncResult result = theFile.BeginRead(buffer, 0, 8192, AcceptResults, state); 
} 

if(result.CompletedSynchronously) 
{ 
    // is it required for us to call AcceptResults ourselves in this case? 
    // or did BeginRead already call it for us, on this thread or another? 
} 

कहाँ AcceptResults है:

void AcceptResults(IAsyncResult result) 
{ 
    lock(theFile) 
    { 
     int bytesRead = theFile.EndRead(result); 

     // if we guarantee that the offset of the original call was at least 8192 bytes from 
     // the end of the file, and thus all 8192 bytes exist, can the FileStream read still 
     // actually read fewer bytes than that? 

     // either: 
     if(bytesRead != 8192) 
     { 
      Panic("Page read borked"); 
     } 

     // or: 
     // issue a new call to begin read, moving the offsets into the FileStream and 
     // the buffer, and decreasing the requested size of the read to whatever remains of the buffer 
    } 
} 

मैं उलझन में हूं, क्योंकि प्रलेखन मेरे लिए स्पष्ट नहीं लगता है। उदाहरण के लिए, फ़ाइलस्ट्रीम क्लास का कहना है:

इस प्रकार के किसी भी सार्वजनिक स्थिर सदस्य थ्रेड सुरक्षित हैं। किसी भी इंस्टेंस सदस्यों को थ्रेड सुरक्षित होने की गारंटी नहीं है।

एकाधिक एक साथ अतुल्यकालिक अनुरोध, अनुरोध पूरा करने के क्रम अनिश्चित प्रस्तुत करना:

लेकिन BeginRead के लिए दस्तावेज़ उड़ान में एक से अधिक पढ़ने के लिए अनुरोध कर रहा विचार करने लगता है।

क्या एकाधिक पढ़ने उड़ान में होने की अनुमति है या नहीं? लिखता है? क्या कॉल करने के लिए कॉल के Position के स्थान को सुरक्षित करने और BeginRead पर कॉल करने का यह उचित तरीका है? या क्या उस लॉक को EndRead पर सभी तरह से रखने की आवश्यकता है, इसलिए एक समय में केवल एक ही उड़ान में पढ़ या लिख ​​सकता है?

मैं समझता हूं कि कॉलबैक एक अलग थ्रेड पर होगा, और state, buffer का मेरा संचालन इस तरह से संभालता है कि उड़ान में कई लोगों को पढ़ने की अनुमति होगी।

आगे, क्या कोई यह जानता है कि दस्तावेज़ों में इन प्रश्नों के उत्तर खोजने के लिए कहां है? या किसी व्यक्ति द्वारा किसी लेख में लिखा गया लेख? मैं खोज रहा हूं और कुछ भी नहीं मिला।

प्रासंगिक दस्तावेज: कुछ नई जानकारी के साथ

FileStream class
Seek method
BeginRead method
EndRead
IAsyncResult interface

संपादित

परावर्तक के साथ एक त्वरित जांच से पता चलता है कि BeginRead प्रति-कॉल स्थिति (मूल अपरिवर्तित संरचना के कुछ फ़ील्ड) में स्ट्रीम स्थिति को कैप्चर करता है। ऐसा प्रतीत होता है कि EndRead कम से कम किसी भी स्पष्ट तरीके से स्ट्रीम स्थिति से परामर्श नहीं करता है। यह स्पष्ट रूप से निर्णायक नहीं है, क्योंकि यह एक गैर-स्पष्ट तरीके से हो सकता है या इसे अंतर्निहित देशी एपीआई द्वारा असमर्थित किया जा सकता है।

+0

+1 अच्छी तरह से लिखित प्रश्न। – SLaks

उत्तर

1

हां, प्रलेखन स्केची है। दुर्भाग्यवश, बेहतर दस्तावेज़ों के लिए कोई सुराग नहीं।

संपादित करें: असल में जो डफी की पुस्तक विंडोज पर समवर्ती प्रोग्रामिंग में अध्याय 8 एपीएम है जो एसिंक एपीआई, आईएएसआईएनसीआरयूल्ट और ऐसी (अच्छी किताब और लेखक) बताती है।फिर भी मूलभूत मुद्दा यह है कि एमएसडीएन का कहना है कि आवृत्ति चर धागे सुरक्षित नहीं हैं, इसलिए उपयुक्त सिंक्रनाइज़ेशन की आवश्यकता है।

तो आपके पास फिली के एक ही उदाहरण पर BeginRead को लात मारने वाले कई धागे हैं? BeginRead पृष्ठ इस बात का जिक्र करता है हालांकि: "EndRead को प्रत्येक कॉल के लिए बिल्कुल एक बार कॉल किया जाना चाहिए। एक और पढ़ने शुरू करने से पहले एक पढ़ने की प्रक्रिया को समाप्त करने में विफल होने से डेडलॉक जैसे अवांछित व्यवहार हो सकते हैं।" इसके अलावा आप फ़ाइल ऑब्जेक्ट पर सेक को कॉल कर रहे हैं जबकि अन्य थ्रेड उनके BeginRead कॉलबैक को निष्पादित करने के बीच में हो सकते हैं। बिल्कुल सुरक्षित नहीं है।

+1

यह क्यों मायने रखता है कि एक धागा खोज रहा है जबकि दूसरा कॉलबैक निष्पादित कर रहा है? संभावित रूप से कॉलबैक का मतलब है कि अनुरोधित पढ़ना पूरा हो गया है, है ना? मैं एक BeginRead और मिलान कॉलबैक के बीच समय में खोज को कॉल करने के बारे में अधिक चिंतित हूं। जब तक मुझे कुछ याद नहीं आ रहा है, कॉल के ऊपर कोड EndRead को प्रत्येक कॉल के लिए बिल्कुल एक बार शुरू करें, इस बारे में कुछ अनिश्चितता के बारे में कुछ बताएं कि क्या BeginRead इसके कॉलबैक को आमंत्रित करता है जब IAynynRRultult इसे लौटाता है तो सिंक्रनाइज़ हो जाता है। –

+0

हां यह प्रत्येक BeginRead के लिए एक EndRead है। हालांकि, इस बात की कोई गारंटी नहीं है कि एंड्रैड को एक और थ्रेड शुरू होने से पहले कॉल किया जाएगा, लॉक उस परिदृश्य की रक्षा नहीं करता है। –

+0

ओह, आप यहां ठीक हो सकते हैं, BeginRead पृष्ठ कहता है "विंडोज़ पर, 64 केबी से छोटे सभी आई/ओ ऑपरेशंस बेहतर प्रदर्शन के लिए सिंक्रनाइज़ेशन पूर्ण हो जाएंगे। असिंक्रोनस I/O 64 KB से छोटे बफर आकारों के प्रदर्शन में बाधा डाल सकता है।" इसलिए आप * गारंटी दे रहे हैं कि सभी रीड वास्तव में आपके लॉक द्वारा क्रमबद्ध हैं। लेकिन यदि सभी धागे ताले के माध्यम से क्रमबद्ध होते हैं और सिंक्रोनस पढ़ता है, तो एसिंक एपीआई का उपयोग क्यों परेशान करते हैं? –

संबंधित मुद्दे