Если Вы видите это предупреждение:
предупреждение: получатель 'MyCoolClass' является классом переадресации, и соответствующий @interface не может существовать
, Вам нужно к #import
файл, но можно сделать это в файле реализации (.m) и использовать @class
объявление в заголовочном файле.
@class
(обычно) не устраняет необходимость к #import
файлы, она просто спускает требование ближе туда, где информация полезна.
, Например
, Если Вы говорите @class MyCoolClass
, компилятор знает, что может видеть что-то как:
MyCoolClass *myObject;
Это не должно волноваться ни о чем кроме MyCoolClass
, допустимый класс, и это должно зарезервировать комнату для указателя на него (действительно, просто указатель). Таким образом, в Вашем заголовке, @class
удовлетворяет 90% времени.
Однако, если когда-нибудь необходимо создавать или доступ myObject
участники, необходимо будет сообщить компилятору, каковы те методы. В этой точке (по-видимому, в Вашем файле реализации), Вам будет нужно к #import "MyCoolClass.h"
, для сообщения дополнительной информации компилятора вне просто, "это - класс".
Я думаю, что единственный надежный способ сделать это - попытаться открыть файл исключительно и отловить конкретное исключение. Обычно я ненавижу использовать исключения для нормальной логики приложения, но боюсь, что для этого сценария другого пути нет (по крайней мере, я его еще не нашел):
public bool FileIsDone(string path)
{
try
{
using (File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None))
{
}
}
catch(UnauthorizedAccessException)
{
return false;
}
return true;
}
Не уверен насчет «правильного пути», но вы можете использовать инструмент мониторинга ( FileSystemWatcher
, я думаю) для заполнения внутренней очереди, которую вы используете для отложенной обработки. Или еще лучше: просто используйте очередь для размещения файлов, открытие которых завершилось ошибкой, чтобы вы могли повторить их позже.
Если вы используете FileSystemWatcher , я не думаю, что есть надежное решение этой проблемы. Один из подходов - попробовать / поймать / повторить попытку позже.
Один из подходов, который я всегда использую, - это создать в конце моей копии / передачи файл с именем "token.txt" без содержимого. Идея заключается в том, что этот файл будет создан только в конце операции передачи, поэтому вы можете отслеживать создание этого файла, и когда этот файл создается, вы начинаете работать со своими файлами. Не забывайте всегда стирать этот файл токена, когда начинаете обрабатывать свои файлы.
Вы также должны учитывать такие случаи, как: файл используется другой программой, файл был удален (не удалось скопировать) и т. Д.
Используйте расширенную обработку исключений, чтобы охватить все важные случаи, которые могут произойти.
В зависимости от обстоятельств, цикл повтора, вероятно, лучшее, что вы можете сделать, если у вас нет контроля над процессом копирования.
Если у вас есть контроль:
Фактически, чтобы избежать состояний гонки, единственное безопасное решение - повторить попытку.
Если вы сделаете что-то вроде:
while (file is locked)
no-op()
process file()
Вы рискуете, что другой процесс перейдет между защитой while и выписка из файла процесса. Независимо от того, как реализовано ваше «ожидание доступности файла», если вы не можете гарантировать, что после разблокировки вы будете первым процессом, получившим к нему доступ, вы можете не быть этим первым пользователем.
Это более вероятно, что это может показаться на первый взгляд, особенно если файл просматривают несколько человек, и в частности, если они используют что-то вроде наблюдателя файловой системы. Конечно, даже тогда это маловероятно ...
Файлы большие?
Может быть, вы могли бы попытаться вычислить контрольную сумму md5 для файла?
Если вы поместите хэш md5 в имя файла, вы сможете получить его и попытаться пересчитать контрольную сумму файла. Когда md5 совпадает, можно предположить, что файл готов.
byte[] md5Hash = null;
MD5 md5 = new MD5CryptoServiceProvider();
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
md5Hash = md5.ComputeHash(fs);
StringBuilder hex = new StringBuilder();
foreach (byte b in md5Hash)
hex.Append(b.ToString("x2"));