1

次のような単純なコードでアプリケーションを呼び出そうとしています

public void Run(string command)
{
    Process proc = new Process();
    proc.StartInfo.FileName = "acvTemp.exe";
    proc.StartInfo.Arguments = command;             

    proc.Start();

    proc.WaitForExit();
}

私が起動している fileName プロセスは、実際に新しいウィンドウを生成します。no exit にするいくつかのコマンドで起動されています。いえ

command = acvtest.exe /launch /wait /log:<temp.log>

したがって、acvtest.exe がマシン上で実行を開始し、実際にはまだ実行されているため、次のような他のコマンドを実行できます。

acvtest.exe /getid:<name>

これは、アプリケーションを手動で使用する方法です。

acvtest.exe /launch /wait /log:<temp.log>
acvtest.exe /getid:<name>

実際の /launch プロセスがシェル コマンド プロンプトに戻ることに注意してください。これは、/launch で新しいコマンド ウィンドウが開かれ、/getid の出力が実際にログに書き込まれるためです。

私の問題は、最初の /launch または /getid コマンドが実行されたときに、ログでハンドルが解放される前に、waitforexit() が終了しているように見えることです。(一部の子スレッドが終了する前にある可能性がありますか?)

つまり、次のコマンドは、スリープ状態にするか待機するまで失敗します。waitforexit() でも

 Run("/launch /wait /log:<temp.log>");
 Run("/getid:<name>");
 Run("shutdown");

 //Needs some sleep or wait here

 using (StreamReader reader = new StreamReader("temp.log"))
 {
     Console.WriteLine(reader.ReadToEnd());
 }

上記の 2 つのセクションの間にスリープまたは待機がない場合、ログへのアクセスは失敗し、別のプロセスによって既に使用されているというエラーが表示されます。アプリケーションが実際にプロセスを終了する前に終了しているように見えます。これはアプリケーションに問題がありますか? それを回避するために私にできることはありますか?

新しいシェルが起動されるため、ここで別の Run() コードが必要になる可能性があると思います。

[アップデート]

問題はログ ファイルだけではありません。約 100,000 個のファイル名で Run("/getid:") を実行すると、これらの多くが「リソースが利用できません」というエラーで失敗します。そのため、リソースを解放する前にアプリケーションが終了する可能性があると考えました探しています。

4

3 に答える 3

0

ファイル ロックの問題に対する 1 つの解決策をここで提案します。次に、対象のプロセスの PID を抽出できます。

繰り返しになりますが、プロセスが終了するまでログ ファイルを開いたままにしておくと、そこに「セマフォ」が存在します。

于 2013-10-25T22:44:31.190 に答える
0

次のコードを使用して、読み取り専用としてファイルを開こうとすることができると思います

FileStream fs = File.Open("temp.log", FileMode.Open, FileAccess.Read);

または、次のようなコードを使用します。

try
{
    // some code here ...

    // Try to access the file within 1000 (or whatever is specified) ms.
    FileAccessHelper.WaitForFileAccessibility("test.log", 1000);

    // and here ...
}
catch (FileAccessHelperException e)
{
    // your error handling here...
    Console.WriteLine("Unable to open the file within 1000ms");
}

FileAccessHelper クラスは次のようになります。

namespace CodingFun
{
    using System;
    using System.IO;
    using System.Threading;

    /// <summary>
    /// Represents our FileAccessHelper class.
    /// </summary>
    public static class FileAccessHelper
    {
        /// <summary>
        /// Blocks until the specified file can be accessed or a timeout occurs.
        /// </summary>
        /// <param name="filename">The file which shall be accessed.</param>
        /// <param name="timeout">The timeout in milliseconds.</param>
        /// <param name="accessMode">Specifies the file access mode, default is read only.</param>
        public static void WaitForFileAccessibility(string filename, int timeout, FileAccess accessMode = FileAccess.Read)
        {
            int tries = 0;
            bool readDone = false;

            do
            {
                try
                {
                    // Try to open the file as read only.
                    FileStream fs = File.Open(filename, FileMode.Open, accessMode);

                    // Close it if it worked and...
                    fs.Close();

                    // ... set a flag so that we know we have successfully opened the file.
                    readDone = true;
                }
                catch (Exception e)
                {
                    // increase the counter and...
                    tries++;

                    // ... check if a timeout occured.
                    if ((100 * tries) >= timeout)
                    {
                        throw new FileAccessHelperException(string.Format("Unable to access the file {0} within the specified timeout of {1}ms", filename, timeout), e);
                    }
                    else
                    {
                        // If not just sleep 100 ms.
                        Thread.Sleep(100);
                    }
                }
            }
            while (!readDone);
        }
    }
}

FileAccessHelperException クラスは次のようになります。

namespace CodingFun
{
    using System;
    using System.Runtime.Serialization;
    using System.Security;

    /// <summary>
    /// Represents the FileAccessHelperException class.
    /// </summary>
    public class FileAccessHelperException : Exception
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="FileAccessHelperException"/> class.
        /// </summary>
        public FileAccessHelperException()
            : base()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="FileAccessHelperException"/> class.
        /// </summary>
        /// <param name="message">The message that describes the error.</param>
        public FileAccessHelperException(string message)
            : base(message)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="FileAccessHelperException"/>
        /// class with a specified error message and a reference to the inner
        /// exception that is the cause of this exception.
        /// </summary>
        /// <param name="message">The error message that explains the reason for the exception.</param>
        /// <param name="innerException">
        /// The exception that is the cause of the current exception, or a null reference
        /// if no inner exception is specified.
        /// </param>
        public FileAccessHelperException(string message, Exception innerException)
            : base(message, innerException)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="FileAccessHelperException"/> class with serialized data.
        /// </summary>
        /// <param name="info">
        /// The System.Runtime.Serialization.SerializationInfo that holds the serialized
        /// object data about the exception being thrown.
        /// </param>
        /// <param name="context">
        /// The System.Runtime.Serialization.StreamingContext that contains contextual
        /// information about the source or destination.
        /// </param>
        /// <exception cref="System.ArgumentNullException">
        /// The info parameter is null.
        /// </exception>
        /// <exception cref="System.Runtime.Serialization.SerializationException">
        /// The class name is null or System.Exception.HResult is zero (0).
        /// </exception>
        [SecuritySafeCritical]
        protected FileAccessHelperException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
    }
}

それが役立つことを願っています;-)

于 2013-10-25T23:18:09.283 に答える
0

これはアプリケーションに問題がありますか? それを回避するために私にできることはありますか?

申請に関しては、おそらく全く問題ないと思います。ほとんどの場合、ファイルはオペレーティング システム自体によって完全に解放されていません。

一般的な回避策は、ファイルを読み取る試行を Try/Catch ブロックでラップし、それを遅延のある while ループで囲むか、Timer からそのコードを呼び出すことです。

于 2013-10-25T22:37:41.757 に答える