Tetsuo_DarkK Ответов: 2

Проблемы c# waitforexit нуждаются в помощи как можно скорее


Я ходил вокруг да около с этим вопросом и, кажется, я в растерянности. в основном код находится в таймере для запуска каждые 10 секунд, он должен искать в папке и обрабатывать каждый файл(что он и делает) и удалять этот файл. Но он перестал работать после того, как я попытался исправить проблему замораживания пользовательского интерфейса, которая у меня была, но я пытался использовать поток(Im new). до этого момента все было хорошо, поэтому мне пришлось закомментировать waitforexit, но если у меня нет такой функции, она удалит файлы до того, как обработает их через
prs.FileName = @"C:\dcmtk\bin\storescu-tls.exe";
Не знаю, что нужно, чтобы это исправить. пожалуйста помочь.

Что я уже пробовал:

foreach (string s in files)
            {
                //if (File.Exists(s))
                finalpath = Host + " " + port + " " + s;
                Process pr = new Process();
                ProcessStartInfo prs = new ProcessStartInfo();
                prs.CreateNoWindow = true;
                prs.UseShellExecute = false;
                prs.RedirectStandardOutput = true;
                prs.WindowStyle = ProcessWindowStyle.Hidden;
                prs.FileName = @"C:\dcmtk\bin\storescu-tls.exe";
                prs.Arguments = finalpath;
                textBox2.Text = s;
                
                pr.StartInfo = prs;
               
                ThreadStart ths = new ThreadStart(() => pr.Start());
                Thread th = new Thread(ths);
                th.Start();
                pr.WaitForExit();

                File.Delete(s);

[no name]

Используйте наблюдатель файловой системы

2 Ответов

Рейтинг:
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. Блин, я уже закончил с этой программой, пока не попытался исправить замерзающий пользовательский интерфейс. Акк!!

Рейтинг:
0

Tetsuo_DarkK

хорошо, я немного обновил код: он немного небрежен, но до сих пор я не получил никаких ошибок. Однако мой цикл удаления/перемещения отправленных файлов продолжает блокироваться, потому что другой процесс все еще использует его:

void m_oWorker_DoWork(object sender, DoWorkEventArgs e)
       {
           //NOTE : Never play with the UI thread here...

           //time consuming operation
           for (int i = 0; i < 100; i++)
           {

               {
                   string filepath = (@"C:\MyDir");
                   string[] files = Directory.GetFiles(filepath, "*.*", SearchOption.AllDirectories);
                   for (int index = 0; index < files.Length; index++)
                       foreach (string s in files)
                       {
                           string fileToProcess = filepath;
                           m_oWorker.ReportProgress(100 * index / files.Length, fileToProcess);

                           string port;
                           port = "106";
                           string Host;
                           Host = "192.168.99.13";
                           //string dicompath = @"C:\MyDir";


                           string finalpath = Host + " " + port + " " + s;
                           //textBox1.Text = finalpath;
                           System.Diagnostics.Process pr = System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
                           {
                               CreateNoWindow = true,
                               UseShellExecute = false,
                               RedirectStandardOutput = true,
                               WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
                               FileName = @"C:\dcmtk\bin\storescu-tls.exe",
                               Arguments = finalpath

                           });

                           pr.Start();

                           //File.Move(s, @"C:\MyDels");
                           //Provider Source Folder Path
                           string SourceFolder = @"c:\MyDir\";
                           //Provide Destination Folder path
                           //string DestinationFolder = @"C:\MyDels\";

                           var filess = new DirectoryInfo(SourceFolder).GetFiles("*.*");
                           pr.WaitForExit();
                           if (!m_oWorker.IsBusy)
                               //Loop throught files and Move to destination folder
                               foreach (FileInfo file in filess)
                           {
                               //delete file if already exists
                               File.Delete(SourceFolder + file.Name);

                               //Move the file to destination folder
                               //file.MoveTo(DestinationFolder + file.Name);

                               //System.IO.File.Delete(s);
                               //File.Delete(s);

                           }

                           pr.WaitForExit();
                           Thread.Sleep(50);
                           m_oWorker.ReportProgress(i);

                           //If cancel button was pressed while the execution is in progress
                           //Change the state from cancellation ---> cancel'ed
                           if (m_oWorker.CancellationPending)
                           {
                               e.Cancel = true;
                               m_oWorker.ReportProgress(0);
                               return;
                           }

                       }

                   //Report 100% completion on operation completed
                   m_oWorker.ReportProgress(100);
               }
           }