C # FileStream в Mono - нарушение совместного доступа к файлам - PullRequest
0 голосов
/ 14 сентября 2018

У меня есть приложение C # WinForms, работающее на Raspbian с Mono. У него есть таймер. Когда запускается OnTimedEvent, я проверяю, есть ли у меня эксклюзивный доступ к файлу, который я хочу загрузить (чтобы убедиться, что он закончен, записывается на диск), затем пытаюсь загрузить. Если загрузка прошла успешно, я перемещаю файл в папку архива, в противном случае я оставляю его там и жду следующего события таймера. У меня нет проблем при подключении к Интернету, но когда я тестирую без, и моя загрузка не удается, второй OnTimedEvent получает исключение при проверке того, готов ли тот же файл (снова). Я получаю:

Error message: ***Sharing violation on path 'path'
***HResult: ***-2147024864

Метод проверки готовности файла:

 public static bool IsFileReady(string filename)
    {

        // If the file can be opened for exclusive access it means that the file
        // is no longer locked by another process.
        try
        {
            var inputStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None);

            bool test = inputStream.Length > 0;

            inputStream.Close();
            inputStream.Dispose();

            return test;
        }
        catch (Exception e)
        {
            //log
            throw e;
        }
    }

Это то, что выполняется на OntimedEvent:

            var csvFiles = from f in di.GetFiles()
                        where f.Extension == ".csv"
                        select f;  //get csv files in upload folder

            foreach (var file in csvFiles)
            {
                if (IsFileReady(file.FullName))  //check that file is done writing before trying to move.
                {
                    bool IsUploadSuccess = await WritingCSVFileToS3Async(file);//.Wait();  //upload file to S3

                    if (IsUploadSuccess)
                    {
                        File.Move(file.FullName, archivePath + file.Name);  //move to completed folder if upload successful. else, leave there for next upload attempt
                    }
                }
            }

Из того, что я могу понять, похоже, что мой первый FileStream (File.Open) все еще заблокировал файл, когда запускается второе событие. Тем не менее, я добавил .Close () и .Dispose () в метод IsFileReady, но это, похоже, не работает.

Любая помощь будет оценена!

РЕДАКТИРОВАТЬ: ниже метод WritingCSVFileToS3Async.

static async Task<bool> WritingCSVFileToS3Async(FileInfo file)
    {
        try
        {
            client = new AmazonS3Client(bucketRegion);

            // Put the object-set ContentType and add metadata.
            var putRequest = new PutObjectRequest
            {
                BucketName = bucketName,
                Key = file.Name,
                FilePath = file.FullName ,
                ContentType = "text/csv"
            };
            //putRequest.Metadata.Add("x-amz-meta-title", "someTitle"); //don't need meta data at this time

            PutObjectResponse response = await client.PutObjectAsync(putRequest);

            if (response.HttpStatusCode == System.Net.HttpStatusCode.OK)
                return true;
            else
                return false;
        }
        catch (AmazonS3Exception e)
        {
            ErrorLogging.LogErrorToFile(e);
            return false;
        }
        catch (Exception e)
        {
            ErrorLogging.LogErrorToFile(e);
            return false;
        }

Кроме того, я запустил то же приложение в Windows и получаю похожее исключение:

The process cannot access the file 'path' because it is being used by another process.

1 Ответ

0 голосов
/ 17 сентября 2018

Мне кажется, я нашел проблему. Я заметил, что я не ловил исключение тайм-аута клиента для запроса PUT (не подключен к Интернету). Мой интервал таймера был 20 секунд, что меньше, чем тайм-аут клиента S3 (30 секунд). Таким образом, клиент все еще связывал файл к моменту запуска второго события таймера, что привело к нарушению прав доступа. Я увеличил интервал таймера до 60 секунд и теперь ловлю исключение тайм-аута клиента и могу обработать его до следующего события таймера.

Спасибо за вашу помощь.

...