Мне не хватает «представителя», чтобы комментировать, так что, надеюсь, этот «ответ» в порядке ...
Принятый ответ - это именно то, что я искал, и он отлично работает, но люди здесь и по аналогичным вопросам подвергли сомнению полезность проверки, заблокирован ли файл. Правильно, что служебная функция для проверки, заблокирован ли файл, не очень полезна, потому что при следующем утверждении статус мог измениться.
Но шаблон попытки выполнить операцию блокировки и затем по-разному реагировать на ошибки блокировки по сравнению с общими ошибками является допустимым и полезным. Самое очевидное, что нужно сделать, это немного подождать и повторить операцию. Это можно обобщить в вспомогательную функцию, например:
protected static void RetryLock(Action work) {
// Retry LOCK_MAX_RETRIES times if file is locked by another process
for (int i = 1; i <= LOCK_MAX_RETRIES; i++) {
try {
work();
return;
} catch (IOException ex) {
if (i == LOCK_MAX_RETRIES || (uint) ex.HResult != 0x80070020) {
throw;
} else {
// Min should be long enough to generally allow other process to finish
// while max should be short enough such that RETRIES * MAX isn't intolerable
Misc.SleepRandom(LOCK_MIN_SLEEP_MS, LOCK_MAX_SLEEP_MS);
}
}
}
} // RetryLock
... который затем можно использовать так:
public string DoSomething() {
string strReturn = null;
string strPath = @"C:\Some\File\Path.txt";
// Do some initial work...
//----------------------------------------------------------------------------------------------------
// NESTED FUNCTION to do main logic, RetryLock will retry up to N times on lock failures
Action doWork = delegate {
using (FileStream objFile = File.Open(strPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) {
// Does work here if lock succeeded, else File.Open will throw ex
strReturn = new StreamReader(objFile).ReadLine();
}
}; // delegate doWork
//----------------------------------------------------------------------------------------------------
RetryLock(doWork); // Throws original ex if non-locking related or tried max times
return strReturn;
}
... в любом случае, просто отправка сообщений на случай, если кто-то с похожими потребностями сочтет эту модель полезной.