C# 等待文件存在

C# 等待文件存在,c#,asp.net,asp.net-web-api,C#,Asp.net,Asp.net Web Api,我已经使用WebAPI2编写了一组web服务。他们最终会调用一个CMD程序,启动OpenEdge进程客户端,传递格式化的XML字符串,然后通过调用.p过程将记录插入OpenEdge进程数据库(WebSpeed不是选项) p文件有一组针对进度应用程序运行的业务逻辑。它随后在完成时生成一个包含节点的XML文件。如果这个节点是空的,那么它工作了。如果文件不存在或节点包含文本。。。它失败了。然后,我读取这个XML文件,并在Web Api中将节点的内容传递回客户机 目前,从调用CMD/Progress小程

我已经使用WebAPI2编写了一组web服务。他们最终会调用一个CMD程序,启动OpenEdge进程客户端,传递格式化的XML字符串,然后通过调用.p过程将记录插入OpenEdge进程数据库(WebSpeed不是选项)

p文件有一组针对进度应用程序运行的业务逻辑。它随后在完成时生成一个包含节点的XML文件。如果这个节点是空的,那么它工作了。如果文件不存在或节点包含文本。。。它失败了。然后,我读取这个XML文件,并在Web Api中将节点的内容传递回客户机

目前,从调用CMD/Progress小程序到尝试读取XML文件,给服务器运行.p文件和创建所述XML文件的时间,存在10秒的静态延迟。不过,这并不太好,偶尔会向客户端返回一个错误,因为它找不到文件,但是,由于服务器负载异常高,文件是在响应返回后1秒创建的。或者,当响应可以在2秒钟内处理时,人们被迫等待10秒钟

我需要想出一种方法来“检查文件是否存在”,直到超时时间过去。我做了一些研究,找不到任何适合WebAPI环境的东西。有人有什么建议吗

下面的代码-原谅我。我一直在学习,因为我一直都在学习,我对这一点非常陌生

控制器

// the request date/time
DateTime requestDate = DateTime.Now;
// list of validation errors
List<string> ohValidation = new List<string>();
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;
    }
GetFullFilePath(可能合并为fullFileName)

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;

    }
私有静态列表getXmlErrorArray(字符串文件路径)
{
列表输出
=新列表();
//从XML文件中读取文本
使用(TextReader txtReader=新的StreamReader(文件路径))
{
XmlSerializer xs
=新的XmlSerializer(typeof(JobError));
//对xml文本进行反序列化
//对于强类型对象
JobError结果=(JobError)xs.Deserialize(txtReader);
//如果xml文件包含错误-将其返回给客户端
如果(!string.IsNullOrEmpty(result.ErrorText))
output.Add(result.ErrorText);
//检查在不同节点下创建的SoR错误
if(result.LineError!=null)
{
List lineErrs=result.LineError.ToList();
foreach(LineError中的LineError le)
{
output.Add(le.SorCode+“:”+le.Error);
}
}
}
返回输出;
}

好的-所以我认为我把问题复杂化了

我没有等待文件存在,而是在CallInsertProgram方法中添加了一行,如下所示(如RB建议的那样)

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();

            // ADDED
            p.WaitForExit(60000);
        }
    }
    catch (Exception e)
    {
        throw new OpenHousingException(e.Message.ToString());
    }

}

这可以确保在移动到下一行之前完成Progress cmd applet,此时将创建XML(如果失败,则不创建)。初始测试运行良好。有人能预见这种方法会出现任何问题吗?

CMD程序是同步运行还是异步运行?如果是同步运行,则您只需等待测试完成,然后读取输出文件。如果是异步运行,则最简单的方法是每1秒轮询一次文件系统,查看是否文件已创建:
while(!file.Exists(“myfile.xml”){Thread.Sleep(1000);}
signar可能有帮助-或手动轮询(HEAD请求)以固定的时间间隔,直到文件available@Developer从他的问题来看,我认为他可以同步地等待客户呼叫,直到文件可用。他只是想确保这是尽可能快和可靠的。亚当:你能澄清一下吗?@RB。-在这种情况下,他一开始就不会出现这个错误。目前re是从调用CMD/Progress小程序到尝试读取XML文件的静态延迟10秒->我认为读取XML文件是另一种延迟call@Developer我明白你的意思了-我读到所有这些都发生在一个调用的上下文中,因为行
,然后我读取这个XML文件并传递节点的内容回到Web Api中的客户端。
-Adam:您肯定需要澄清-这里是有1个HTTP调用,还是有2个?!
抛出新OpenHousingException(e.Message.ToString());
不是一个好主意。您正在丢失大量信息,执行
抛出新OpenHousingException(“callInsertProgram失败”,e);
将整个异常作为内部异常传入,并将堆栈跟踪等信息保持不变。
    private static string getFullFilepath(string filename, string folder)
    {
        return fileLocation + folder + @"\" + filename;
    }
    private static bool checkXmlFileExists(string filepath)
    {
        bool fileExists = false;

        if (File.Exists(filepath))
        {
            fileExists = true;
        }

        return fileExists;
    }
    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;

    }
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();

            // ADDED
            p.WaitForExit(60000);
        }
    }
    catch (Exception e)
    {
        throw new OpenHousingException(e.Message.ToString());
    }

}