Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / невозможно открыть файл с одним именем в разных потоках, блокируется свлчь / 12 сообщений из 12, страница 1 из 1
13.11.2013, 10:35
    #38463070
Charles Weyland
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
невозможно открыть файл с одним именем в разных потоках, блокируется свлчь
В упрощённом виде моя программа выглядит так:
В проводнике копирую в c:\ существующий файл file.txt

Выполняю START()

файл читается и удаляется программой, код ниже. В проводнике его нет, прога продолжает работать

В проводнике копирую в c:\ существующий файл file.txt

Выполняю START()

Выдаётся ошибка, которую я отобразил.
Как её вообще отладить - я не знаю..
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
    public class ОбработкаФайлов
    {
        Thread thread;
        object locker = new object();

        public void START()
        {
            var a = new Thread(ProcessFile);
            a.Start("c:\\file1.txt");
            a.Name = "file1.txt";
        }

        private void ProcessFile(object file)
        {
            ReadTXTFile(file.ToString());
            DelFile(file.ToString());
        }
        private void ReadTXTFile(string filename)
        {
            string text = System.IO.File.ReadAllText(filename); //файл используется другим процессом
            using (StreamWriter file = new StreamWriter("C:\\file2.txt"))
            {
                .....
                file.Close();
            }
        } 
...
Рейтинг: 0 / 0
13.11.2013, 10:35
    #38463071
Charles Weyland
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
невозможно открыть файл с одним именем в разных потоках, блокируется свлчь
Удаление, возможно, причина всех бед,
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
        private void DelFile(string file)
        {
            bool success = false;
            DateTime start = DateTime.Now;
            while (!success)
            {
                try
                {
                    File.Delete(file.ToString());
                    success = true;
                }
                catch (Exception e)
                {
                    //ToDo: обработать exception
                    if ((DateTime.Now - start).TotalSeconds > 100)
                        break;
                }
            }
        }
    }
...
Рейтинг: 0 / 0
13.11.2013, 11:22
    #38463133
carrotik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
невозможно открыть файл с одним именем в разных потоках, блокируется свлчь
Charles Weyland,

... во многих случаях именно удаление держит файл .. обычно, такой костыль как Sleep(500), т.е. полсекунды, помогает ...
...
Рейтинг: 0 / 0
13.11.2013, 11:37
    #38463177
Charles Weyland
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
невозможно открыть файл с одним именем в разных потоках, блокируется свлчь
Подкорректировал удаление
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
        private void DelFile(string file)
        {
            bool success = false;
            DateTime start = DateTime.Now;
            while (!success)
            {
                try
                {
                    File.Delete(file.ToString());
                    using (StreamWriter f = new StreamWriter(file))
                    {
                        f.WriteLine("sdfdf " + file);
                        f.Close();
                    }
                    string text = System.IO.File.ReadAllText(file);
                    Console.WriteLine(text);
                    
                    success = true;
                }
                catch (Exception e)
                {
                    //ToDo: обработать exception
                    if ((DateTime.Now - start).TotalSeconds > 100)
                        break;
                }
            }
        }
    }


по вашей логике, он должен был блокироваться на выделенной строке. Но работает нормально.
...
Рейтинг: 0 / 0
13.11.2013, 11:52
    #38463214
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
невозможно открыть файл с одним именем в разных потоках, блокируется свлчь
Charles Weyland, в данном коде не видно мест где file1.txt может быть надолго занят твоим кодом. Функция ReadAllText читает файл и тут же его закрывает. Возможно проблема в другой части кода, возможно в другой программе (например, антивирус). Посмотреть какой процесс держит файл открытым можно, например, с помощью Process Explorer . Запускаем Process Explorer, нажимаем Ctrl+F, вводим file1.txt и смотрим кто занял файл.

В данном коде файл спокойно можно удалять сразу после прочтения:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
public class ОбработкаФайлов
{
	public void START()
	{
		var processFileThread = new Thread(ProcessFile);
		processFileThread.Start("c:\\file1.txt");
		processFileThread.Name = "file1.txt";
	}
	
	private void ProcessFile(object data)
	{
		string filename = (string)data;
		
		string text = System.IO.File.ReadAllText(filename);
		System.IO.File.Delete(filename);
		
		using (StreamWriter file = new StreamWriter("C:\\file2.txt"))
		{
			// ...
		}
	}
}


Еще один момент. Функция ProcessFile не является реентерабельной. То есть если запустить несколько потоков, то мы с большой вероятностью получим исключение в строке new StreamWriter("C:\\file2.txt") т.к файл будет занят другим потоком. Я бы добавил страховку в виде блокировки:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
public class ОбработкаФайлов
{
	private object processFileLock = new object();
	
	public void START()
	{
		var processFileThread = new Thread(ProcessFile);
		processFileThread.Start("c:\\file1.txt");
		processFileThread.Name = "file1.txt";
	}
	
	private void ProcessFile(object data)
	{
		string filename = (string)data;
		lock (processFileLock)
		{
			string text = System.IO.File.ReadAllText(filename);
			System.IO.File.Delete(filename);
		
			using (StreamWriter file = new StreamWriter("C:\\file2.txt"))
			{
			}
		}
	}
}


По поводу функции удаления я тебе уже писал ( 15002768 ) что так делать не следует. Вместо попыток постоянно удалить файл следует переписать код так чтобы на момент удаления файл не был занят твоим приложением. Тогда удаление будет проходить с первой попытки. Если нет, то значит он занят другим приложением и это уже не наша проблема.

P.S. В конце блока using y тебя стоит вызов file.Close();. Его можно убрать т.к. using делает это за тебя.
...
Рейтинг: 0 / 0
13.11.2013, 15:04
    #38463487
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
невозможно открыть файл с одним именем в разных потоках, блокируется свлчь
Charles Weyland-Выполняю START()
- файл читается и удаляется программой, код ниже. В проводнике его нет, прога продолжает работать
- В проводнике копирую в c:\ существующий файл file.txt
- Выполняю START()
А что у тебя служит триггером для запуска START()? Случайно не событие Created от FileSystemWatcher? Если да, то файл может еще быть занят проводником. В таком случае нужно сначала дождаться когда файл станет доступным с помощью таймера или "в лоб" через Thread.Sleep().
...
Рейтинг: 0 / 0
13.11.2013, 15:16
    #38463510
Sergey S
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
невозможно открыть файл с одним именем в разных потоках, блокируется свлчь
И какой размер файлов?
Может он еще не закончил работать с ним?
...
Рейтинг: 0 / 0
13.11.2013, 15:38
    #38463564
Charles Weyland
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
невозможно открыть файл с одним именем в разных потоках, блокируется свлчь
bazileА что у тебя служит триггером для запуска START()? Случайно не событие Created от FileSystemWatcher?
да, абсолютно! То есть, кроме как sleep, вариантов, в общем-то, нет?

в таком случае, есть ли функция, которая может определить, блокирован ли файл?
типа:
Код: c#
1.
bool v = IsFileBlocked(filename);
...
Рейтинг: 0 / 0
13.11.2013, 15:39
    #38463569
Charles Weyland
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
невозможно открыть файл с одним именем в разных потоках, блокируется свлчь
а то ловля эксепшенов мне как-то в этом случае не очень нравится.
...
Рейтинг: 0 / 0
13.11.2013, 16:08
    #38463650
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
невозможно открыть файл с одним именем в разных потоках, блокируется свлчь
Кроме Sleep еще можно использовать таймер, как было написано выше. Хотя с формальной точки зрения Sleep и таймер в рамках данной задачи одинаковы.

Функции IsFileBlocked нет. Без обработки исключений не обойтись. Пример реализации:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
private static string TryReadTextFile(string filename, int maxRetries)
{
	for (int i=0; i<maxRetries; i++)
	{
		try
		{
			return File.ReadAllText(filename);
		}
		catch (IOException)
		{
		}
		
		Thread.Sleep(500);
	}
	
	return null;
}

private void ProcessFile(object data)
{
	string filename = (string)data;
	
	string text = TryReadTextFile(filename, 10);
	if (text == null) return;
	
	File.Delete(filename);
	
	using (StreamWriter file = new StreamWriter("C:\\file2.txt"))
	{
		// ...
	}
}
...
Рейтинг: 0 / 0
13.11.2013, 16:38
    #38463707
Charles Weyland
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
невозможно открыть файл с одним именем в разных потоках, блокируется свлчь
Спасибо за совет!

есть небольшая загвоздка со слипом.

в некоторой функции, которая запускается в отдельном потоке, записано:
Код: c#
1.
2.
3.
            Console.WriteLine("до слипа");
            Thread.Sleep(500);
            Console.WriteLine("после слипа");



и 50/50, либо с интервалом в полминуты выведет обе строки, либо выведет первую и дальше выполнять ничего не станет. Как такое может быть... убийством потоков нигде не занимаюсь. Только начался поток, сразу он завис.
...
Рейтинг: 0 / 0
14.11.2013, 00:27
    #38464310
bazile
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
невозможно открыть файл с одним именем в разных потоках, блокируется свлчь
Charles Weyland, даже не знаю. Надо целиком приложение видеть чтобы понять.
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / невозможно открыть файл с одним именем в разных потоках, блокируется свлчь / 12 сообщений из 12, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]