Рейтинг:
2
Richard Deeming
Зовущий pr.Start()
в новом Thread
он не собирается размораживать ваш пользовательский интерфейс. Это не акт запуска процесса, который вызывает замораживание пользовательского интерфейса; это ожидание завершения процесса-вот в чем проблема.
Вы не можете удалить файл до тех пор, пока процесс не завершится, поэтому вы должны сохранить WaitForExit
.
Самым простым решением было бы использовать BackgroundWorker[^] для обработки файлов в фоновом потоке:
private void ProcessFiles()
{
if (!backgroundWorker.IsBusy)
{
string[] files = Directory.GetFiles(Path, "*");
if (files.Length != 0)
{
backgroundWorker.RunWorkerAsync(files);
}
}
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
string[] files = (string[])e.Argument;
for (int index = 0; index < files.Length; index++)
{
string fileToProcess = files[index];
backgroundWorker.ReportProgress(100 * index / files.Length, fileToProcess);
string finalpath = Host + " " + port + " " + fileToProcess;
Process pr = Process.Start(new ProcessStartInfo
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
WindowStyle = ProcessWindowStyle.Hidden,
FileName = @"C:\dcmtk\bin\storescu-tls.exe",
Arguments = finalpath
});
pr.WaitForExit();
File.Delete(s);
}
}
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
textBox2.Text = (string)e.UserState;
}
Пример класса BackgroundWorker для начинающих[
^]
Многопоточность с использованием фонового рабочего, C#[
^]
Tetsuo_DarkK
Нужно ли мне все еще ставить это в таймер? Я пытался создать функцию, которая постоянно проверяет папку на наличие файлов, а затем обрабатывает их.
Richard Deeming
Да, вам все равно понадобится таймер, чтобы запустить процесс по расписанию.
Рассматривали ли вы возможность использования Класса filesystemwatcher[^] вместо этого? Это позволит вам обрабатывать файлы по мере их создания, а не проверять наличие новых файлов каждые несколько секунд.
0x01AA
Но действительно ли FileSystemWatcher безопасен? Исходя из опыта, я не буду доверять ему, например, просмотр файлов на общем ресурсе, поэтому я всегда добавляю таймер в качестве "резервной копии". Это неправильно/слишком много?
Richard Deeming
Я не склонен использовать его на сетевых путях, но на локальных путях он кажется довольно безопасным. Проблемы возникают только в том случае, если обработчик событий занимает слишком много времени и очередь заполняется.
Tetsuo_DarkK
Я пытался использовать этот код, но, похоже, мне что-то не хватает. BackGroundWorker вроде бы нет.
Richard Deeming
Это BackgroundWorker
(NB: Строчная буква "Г"), и она находится в System.ComponentModel
пространство имен.
Если вы используете проект Windows Forms, вам нужно перетащить его из панели инструментов в свою форму и назвать ее backgroundWorker
, установите WorkerReportsProgress
собственность на true
, и подключить два обработчика событий.
Если вы используете что-то другое, вам нужно будет создать BackgroundWorker
поле называется backgroundWorker
, и инициализировать его в вашем наборе конструкторов WorkerReportsProgress = true;
и подключи два обработчика событий.
Tetsuo_DarkK
До сих пор не могу заставить его бежать. Никаких ошибок просто не происходит...
private void m_oWorker_DoWork(отправитель объекта, DoWorkEventArgs e)
{
string[] files = (string[])e. аргумент;
for (int index = 0; index < files.Длина; индекс++)
{
строка fileToProcess = files[index];
m_oWorker.ReportProgress(100 * index / files.Длина, филетопроцесс);
строку порт;
порт = " 106";
строка host;
Хост = " 192.168.99.13";
//string dicompath = @"C:\MyDir";
строка finalpath = Host + ""+ port + "" + fileToProcess;
Процесс pr = процесс.Start (new ProcessStartInfo
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
WindowStyle = ProcessWindowStyle.Скрытый,
Имя Файла = @"C:\dcmtk\bin\storescu-tls.exe",
Аргументы = finalpath
});
пр.Начать();
пр.WaitForExit();
Файл.Удалить (fileToProcess);
}
Tetsuo_DarkK
частный недействительными button3_Click(объект отправителя, EventArgs в электронной)
{
btnStartAsyncOperation.Включено = ложь;
btnCancel.Включен = истина;
// Запустите асинхронную операцию здесь
m_oWorker.RunWorkerAsync();
Richard Deeming
m_oWorker.RunWorkerAsync();
Вы не передаете список файлов для обработки. Если вы отладите свой код, то увидите, что (string[])e.Argument
возвращается null
, и следующая строка бросает NullReferenceException
.
Сравните это с кодом, который я опубликовал:
string[] files = Directory.GetFiles(Path, "*");
if (files.Length != 0)
{
backgroundWorker.RunWorkerAsync(files);
}
Это передает список файлов для обработки.
Tetsuo_DarkK
хорошо, я немного обновил код: он немного небрежен, но до сих пор я не получил никаких ошибок. Однако мой цикл удаления/перемещения отправленных файлов продолжает блокироваться, потому что другой процесс все еще использует его:
void m_oWorker_DoWork(отправитель объекта, DoWorkEventArgs e)
{
// Примечание: никогда не играйте с потоком пользовательского интерфейса здесь...
// трудоемкая операция
for (int i = 0; i < 100; i++)
{
{
строку путь к файлу = (@"C:\MyDir");
string[] files = каталог.Заражен(путь_к_файлу, ""., Searchoption указывает, нужно.AllDirectories);
for (int index = 0; index < files.Длина; индекс++)
foreach (строка s в файлах)
{
строка fileToProcess = путь к файлу;
m_oWorker.ReportProgress(100 * index / files.Длина, филетопроцесс);
строку порт;
порт = " 106";
строка host;
Хост = " 192.168.99.13";
//string dicompath = @"C:\MyDir";
строка finalpath = Host + ""+ port + "" + s;
//textBox1. Text = finalpath;
Система.Диагностика.Процесс pr = система.Диагностика.Процесс.Запустить(новую систему.Диагностика.Изменение панели
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
WindowStyle = Система.Диагностика.ProcessWindowStyle.Скрытый,
Имя Файла = @"C:\dcmtk\bin\storescu-tls.exe",
Аргументы = finalpath
});
пр.Начать();
//Файл.Move(s, @"C:\MyDels");
// Путь К Исходной Папке Поставщика
строка SourceFolder = @"c:\MyDir\";
// Укажите путь к папке назначения
//string DestinationFolder = @"C:\MyDels\";
var filess = new DirectoryInfo (SourceFolder).GetFiles(".");
пр.WaitForExit();
если (! m_oWorker.IsBusy)
//Цикл через файлы и переместить в папку назначения
foreach (файл FileInfo в filess)
{
// удалить файл, если он уже существует
Файл.Удалить (SourceFolder + file.Name);
// Переместить файл в папку назначения
//файл.MoveTo(DestinationFolder + file.Name);
//Системы.ИО.Файл.Удалить(ы);
//Файл.Удалить(ы);
}
пр.WaitForExit();
Нить.Сон(50);
m_oWorker.ReportProgress (i);
//Если кнопка отмены была нажата во время выполнения
//Изменить состояние с отмены - - - > cancel'Ed
если (m_oWorker.CancellationPending)
{
е.Отмена = истина;
m_oWorker.ReportProgress(0);
вернуть;
}
}
// Отчет о 100% завершении операции завершен
m_oWorker.ReportProgress(100);
}
Richard Deeming
То IsBusy
собственность есть всегда собираюсь вернуться true
в DoWork
обработчик событий, так что я не вижу, как ваш цикл будет когда-либо выполняться.
Tetsuo_DarkK
это может быть проблема, которую я вижу. но когда я комментирую эту часть, она говорит мне, что не может получить доступ к этому файлу, потому что его использует другой процесс. Это похоже на то, что waitfor exit не работает, поэтому он пытается удалить файл, пока storescu отправляет файл. Не знаю, как это исправить. Вот почему я пробовал Isbusy.
Richard Deeming
Предполагая, что именно запущенный вами процесс удерживает файл заблокированным, попробуйте переместить Thread.Sleep(50)
строка перед циклом, который перемещает / удаляет файлы.
Tetsuo_DarkK
Я продвинулся немного дальше со своим кодом,и мне пришлось немного изменить его. Теперь используется наблюдатель файловой системы для запуска процесса storescu, но он запускает процесс storescu для каждого созданного файла. Есть ли способ заставить его сделать это только один раз?
Проблема в том, что он работает нормально, но каждый файл-это отдельная запись. Поэтому storescu запускает соединение, отправляет файл, завершает соединение и повторяет его до тех пор, пока папка не опустеет. У Storescu есть опция Scan directory, которую я использую сейчас, поэтому мне нужно, чтобы она остановила filesystemwatcher, как только он запустит процесс для storescu с битом scan directory, который отправляет все файлы в папке как одно соединение на сервер.
fsw_Changed недействительным(объект отправителя, FileSystemEventArgs е)
{
//string filepath = dicompath;
//string [] files = каталог.GetFiles(filepath,"*.*", SearchOption.AllDirectories);
//for (int index = 0; index < files.Длина; индекс++)
строку порт;
порт = Ports2.Текст;
строка host;
Узел = Вызовите Список.Текст;
//string dicompath = @"C:\MyDir";
строка finalpath = Host + ""+ port + "- f " + "+r +sd " + dicompath;
//textBox1. Text = finalpath;
Процесс startInfo2 = новый процесс();
startInfo2.Информацию.CreateNoWindow = true;
startInfo2. StartInfo. UseShellExecute = false;
startInfo2.StartInfo. RedirectStandardOutput = true;
startInfo2.Информацию.WindowStyle = ProcessWindowStyle.Скрытый;
startInfo2.Информацию.Имя Файла = @"C:\dcmtk\bin\storescu.exe";
//startInfo2.Информацию.Имя Файла = @"C:\NEW_DCMTK\bin\Debug\storescu.exe";
startInfo2.Информацию.Аргументы = @ " 192.168.99.13 106 +f +sd C:\MyDir\";
//startInfo2.Информацию.Аргументы = finalpath;
var runningProcessByName = процесс.GetProcessesByName(@"C:\dcmtk\bin\storescu.exe");
if (runningProcessByName.Длина = = 0)
{
startInfo2.Начать();
}
startInfo2.WaitForExit();
//fileSystemWatcher1.EnableRaisingEvents = ложь;
Нить.Сон(2000);
startInfo2. WaitForExit(500);
//Файл.Move(s, @"C:\MyDels");
// Путь К Исходной Папке Поставщика
строки SourceFolder = форма form1.dicompath;
// Укажите путь к папке назначения
//string DestinationFolder = @"C:\MyDels\";
var filess = new DirectoryInfo (SourceFolder).GetFiles("*.*");
//Цикл через файлы и переместить в папку назначения
foreach (файл FileInfo в filess)
{
пробовать
{
Системы.ИО.Файл.Удалить (e. FullPath);
}
поймать (исключение бывший)
{
Ящик для сообщений.Шоу (напр. источник: "О боже, что-то не получилось. повторите попытку позже... Извините!", MessageBoxButtons.Хорошо, MessageBoxIcon.Звездочка);
}
}
}
Tetsuo_DarkK
Я посмотрю в FileSystemWatcher. Блин, я уже закончил с этой программой, пока не попытался исправить замерзающий пользовательский интерфейс. Акк!!