سؤال

هل يمكنني استخدام FileStream مُنشئ لضمان وصول عملية واحدة فقط إلى ملف في وقت واحد؟ هل سيعمل الكود التالي؟

public static IDisposable AcquireFileLock() {
    IDisposable lockObj;
    do {
        // spinlock - continually try to open the file until we succeed
        lockObj = TryOpenLockFile();

        // sleep for a little bit to let someone else have a go if we fail
        if (lockObj == null) Thread.Sleep(100); 
    }
    while (lockObj == null);

    return lockObj;
}

private static FileStream TryOpenLockFile() {
    try {
        return new FileStream(s_LockFileName, FileMode.Create, FileAccess.Read, FileShare.None);
    }
    catch (IOException) {
        return null;
    }
}

على وجه الخصوص ، هو السلوك مع FileMode.Create WRT الذرية عمليات أخرى؟ هل هناك شيء آخر يجب أن أستخدمه؟

تحرير: لكي تكون أكثر تحديداً ، فإن هذا على Microsoft CLR باستخدام الملفات المحلية على جهاز واحد.

هل كانت مفيدة؟

المحلول

هذا سيفعل ما تريد. FileShare.None هو الجزء المهم.

إذا كانت جميع تطبيقات الكاتب على نفس الكمبيوتر ، فيمكنك أيضًا استخدام ملف اسمه MUTEX لتحقيق نفس الهدف دون الحاجة إلى ملف فعلي ، أو للتوسط في الوصول إلى الملف إذا كنت لا تهتم من يكتب إلى الملف الأخير (فقط أن الكتابة ليست متزامنة). قد يوفر لك هذا من الاضطرار إلى إعادة فتح الملف في كل مرة ، وتوفير حظر دلالي بدلاً من Sleep حلقة (أفضل perf).

لاحظ أنه يمكن لأي عملية القرفصاء على ملفك (Mutex) إذا لم يتم التعامل مع الاسم على أنه سر ، أي المعلومات التي يجب الحفاظ عليها آمنة.

نصائح أخرى

سيعمل هذا ، بالنظر إلى التحذيرات التالية:

  • أنت على Windows (على Linux عبر Mono ، هذا لا يصمد لأن أقفال الملفات استشارية ، لذلك تنجح طريقتك دائمًا)
  • أنت تصل إلى ملف محلي (من المحتمل أن يعمل SMB أيضًا ، ولكن من المؤكد أن NFS أو WebDav لن يحدث)
  • ربما يكون التقاط IOException واسعًا جدًا ، فأنت بحاجة إلى التحقق على وجه التحديد من أنها فشلت بسبب انتهاك المشاركة
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top