Я написал набор веб-сервисов с использованием Web Api 2. Они в конечном итоге вызывают программу CMD, которая запускает клиент OpenEdge Progress, передает форматированную XML-строку и затем вставляет записи в OpenEdge Progress базы данных, вызывая процедуру .p (WebSpeed не является опцией).Дождитесь окончания файла
Файл .P имеет набор бизнес-логики для работы с приложением Progress. Затем он создает XML-файл по завершении, содержащий узел < Error>. Если этот узел пуст, значит, он сработал. Если файл не существует или узел содержит текст ... это не удалось. Затем я прочитал этот XML-файл и передал содержимое узла Error> < обратно клиенту в Web Api.
На данный момент существует статическая задержка в 10 секунд после вызова апплета CMD/Progress, попытки чтения XML-файла, чтобы дать серверу время запуска файла .P и создать указанный XML-файл. Однако это не очень удобно, и иногда клиенту возвращается ошибка, потому что он не может найти файл, но файл был создан через 1 секунду после того, как ответ был возвращен из-за ненормально высоких нагрузок сервера. В качестве альтернативы, люди вынуждены ждать 10 секунд, когда ответ может быть обработан через 2 секунды.
Мне нужно придумать способ «проверить, пока файл не существует», пока не истечет время ожидания. Я провел некоторое исследование и не нашел ничего подходящего для среды Web Api. У кого-нибудь есть предложения?
Код ниже - простите меня. Я очень многому научился, поскольку я шел и очень новичок в этом!
Контроллер
// the request date/time
DateTime requestDate = DateTime.Now;
// list of validation errors
List<string> ohValidation = new List<string>();
...
WebExtensions.callInsertProgram(xml, "JOBLOG");
ohValidation = XmlExtensions.ReadProgressXmlFileWithArray(job.logjob.placeref, requestDate, "joblogging");
CallInsertProgram
public static void callInsertProgram(string xml, string program)
{
try
{
using (Process p = new Process())
{
p.StartInfo.FileName = @"C:\Rubixx\runProgress.exe";
p.StartInfo.WorkingDirectory = @"C:\Rubixx";
// stop windows from appearing on the server
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
// set the arguments for running. The program name and xml are passed in as arguments
// wrapped in escaping "\" to stop spaces from being treated as a separator
p.StartInfo.Arguments = "\"" + program + "," + xml + "\"";
p.Start();
}
}
catch (Exception e)
{
throw new OpenHousingException(e.Message.ToString());
}
}
ReadProgressXMLWithArray
public static List<string> ReadProgressXmlFileWithArray(string reference, DateTime requestDateTime, string folder)
{
// new empty list
List<string> output
= new List<string>();
// wait X seconds before doing anything
// to ensure the XML file has time to be created
Delay_Start(fileDelay);
//
string filename = fullFileName(jobno, folder, requestDateTime);
string filepath = getFullFilepath(filename, folder);
if (checkXmlFileExists(filepath))
{
// if so check for the existence of an error message
output = getXmlErrorArray(filepath);
}
else
{
// if no file is found - the call to Progress hasn't executed. So tell the end user.
throw new OpenHousingException("No OpenHousing file could be found");
}
return output;
}
Delay_Start
private static void Delay_Start(int Seconds)
{
DateTime StartTime;
DateTime EndTime;
StartTime = DateTime.Now;
EndTime = StartTime.AddSeconds(Seconds);
do
{ StartTime = DateTime.Now; } while (StartTime < EndTime);
}
FullFileName (необходимо, потому что я не могу быть уверен в XML файла, пока не создано. Формат файла - UniqueReference_DateTimeFileCreated.xml (xxxxxxxx_20160401-1100.xml) Итак, у меня есть подстановочный поиск в папке с уникальной ссылкой).
public static string fullFileName(string jobNo, string folder, DateTime createdDate)
{
string fileName = string.Empty;
string folderPath = fileLocation + folder;
DirectoryInfo dir = new DirectoryInfo(folderPath);
FileInfo[] files = dir.GetFiles(jobNo + "*", SearchOption.TopDirectoryOnly).Where(f => f.CreationTimeUtc > createdDate || f.LastWriteTimeUtc > createdDate).ToArray() ;
foreach (var item in files)
{
fileName = item.Name;
}
if (string.IsNullOrEmpty(fileName))
throw new OpenHousingException("No OpenHousing file could be found");
return fileName;
}
GetFullFilePath (вероятно, может быть объединены в FullFileName)
private static string getFullFilepath(string filename, string folder)
{
return fileLocation + folder + @"\" + filename;
}
CheckXMLFileExists
private static bool checkXmlFileExists(string filepath)
{
bool fileExists = false;
if (File.Exists(filepath))
{
fileExists = true;
}
return fileExists;
}
GetXMLErrorArray
private static List<string> getXmlErrorArray(string filepath)
{
List<string> output
= new List<string>();
// read the text from XML file
using (TextReader txtReader = new StreamReader(filepath))
{
XmlSerializer xs
= new XmlSerializer(typeof(JobError));
// de-serialise the xml text
// to a strongly typed object
JobError result = (JobError)xs.Deserialize(txtReader);
// if the xml file contains an error - return it to the client
if (!string.IsNullOrEmpty(result.ErrorText))
output.Add(result.ErrorText);
//check for SoR errors that are created under a different node
if (result.LineError != null)
{
List<LineError> lineErrs = result.LineError.ToList();
foreach (LineError le in lineErrs)
{
output.Add(le.SorCode + ":" + le.Error);
}
}
}
return output;
}
Выполняет ли программа CMD синхронно или асинхронно? Если это синхронно, вы можете просто подождать, пока это закончится, а затем прочитайте выходной файл. Если это асинхронно, то самый простой подход - просто опросить файловую систему каждые 1 секунду, чтобы узнать, был ли еще создан файл: 'while (! File.Exists (« myfile.xml »)) {Thread.Sleep (1000); } ' –
SignalR может помочь - https://www.asp.net/signalr или ручной опрос (HEAD-запрос) с фиксированными интервалами до тех пор, пока файл не будет доступен – Developer
@Developer. Из его вопроса я думаю, что он нормально с клиентским вызовом синхронно ждет, пока файл доступен - он просто хочет, чтобы это было как можно быстрее и надежнее. ** Адам **: Можете ли вы это прояснить? –