Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 进程无法访问该文件,因为另一个使用streamwriter的进程正在使用该文件_C#_File_Io_Streamwriter - Fatal编程技术网

C# 进程无法访问该文件,因为另一个使用streamwriter的进程正在使用该文件

C# 进程无法访问该文件,因为另一个使用streamwriter的进程正在使用该文件,c#,file,io,streamwriter,C#,File,Io,Streamwriter,我有两个程序:一个C#GUI应用程序和一个访问同一文本文件的C#windows服务 a) the C# GUI application will write/append to the text file b) the windows service will copy the file to a network location every 20 mins. 当操作同时发生时,我收到如下错误消息: 2014/09/08 21:15:56 mscorlib The process cannot

我有两个程序:一个C#GUI应用程序和一个访问同一文本文件的C#windows服务

a) the C# GUI application will write/append to the text file
b) the windows service will copy the file to a network location every 20 mins.
当操作同时发生时,我收到如下错误消息:

2014/09/08 21:15:56 mscorlib
The process cannot access the file 'C:\09082014.log' because it is being used by another process.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at System.IO.StreamWriter.CreateFile(String path, Boolean append)
   at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding, Int32 bufferSize)
   at System.IO.StreamWriter..ctor(String path, Boolean append)
   at DataloggerUI.DataHelper.WriteDataLog(String msg, Int64& downTimeSince)
   at DataloggerUI.Form1.ReceiveData(IAsyncResult asyncResult)
----C#windows服务部分如下所示----------

-------C#windows GUI应用程序代码如下所示-------

GUI应用程序将抛出错误消息。 我的代码中是否有任何错误或错误做法

------------根据Peter的建议将代码修改为以下内容--------------


你至少有两个选择。从概念上讲,最简单的方法是将文件I/O包装在try/catch中,如果发生IOException(并且仅当发生IOException时),则短暂延迟操作(例如Thread.Sleep(),设置计时器),然后重试

另一种方法是使用命名互斥来允许服务和GUI进程协调访问。每个人在尝试各自的操作之前都会获得互斥锁;如果另一个当前正在访问该文件,则尝试获取互斥将导致进程等待,直到另一个完成

重试代码有时会变得凌乱和冗长,因此虽然我认为重试方法更容易理解,但互斥方法实际上更易读,更容易纠正(一旦您费心学习如何创建命名互斥,这并不难,MSDN也有示例).

基于您自己的编辑,这应该是正确的方法:

// try to write maximum of 3 times
var maxRetry = 3;
for (int retry = 0; retry < maxRetry; retry++)
{
    try
    {
        using (StreamWriter sw = new StreamWriter(logfile, true))
        {
            sw.WriteLine("{0} KYEC{1} {2}", tick, Environment.MachineName, msg);

            break; // you were successfull so leave the retry loop
        }
    }
    catch (IOException)
    {
        if(retry < maxRetry - 1)
        {
            System.Threading.Thread.Sleep(2000); // Wait some time before retry (2 secs)
        }
        else
        {
            // handle unsuccessfull write attempts or just ignore.
        }
    }
}
//尝试最多写入3次
var-maxRetry=3;
for(int retry=0;retry

这使您有机会指定重试写入尝试的时间。

您可以在共享读写模式下使用FileStream同时写入和复制文件

请尝试以下代码:

 //To write file use
    using (FileStream fs = new FileStream(fileToReadPath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) 
    {
        using (StreamWriter StreamWriter = new StreamWriter(fs)) 
        {
            StreamWriter.WriteLine(tick + " " + "KYEC" + Environment.MachineName + " " + msg);
            StreamWriter.Close();
        }
    }

//To copy file use
    using (FileStream inStream = new FileStream(fileToReadPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
    {
        using (FileStream outStream = File.Create(fileToWritePath)) 
        {
            while (inStream.Position < inStream.Length) 
            {
                outStream.WriteByte((byte)inStream.ReadByte());
            }
        }
    }
//要编写文件,请使用
使用(FileStream fs=newfilestream(fileToReadPath、FileMode.Append、FileAccess.Write、FileShare.ReadWrite))
{
使用(StreamWriter StreamWriter=新StreamWriter(fs))
{
StreamWriter.WriteLine(勾选+“”+“KYEC”+环境.MachineName+“”+msg);
StreamWriter.Close();
}
}
//要复制文件,请使用
使用(FileStream inStream=newfilestream(fileToReadPath,FileMode.Open,FileAccess.Read,FileShare.ReadWrite))
{
使用(FileStream outStream=File.Create(fileToWritePath))
{
while(流内位置<流内长度)
{
outStream.WriteByte((字节)inStream.ReadByte());
}
}
}

这样,您就可以完成任务,而不会被其他进程错误使用。

windows服务如何决定何时开始复制文件?请解释该过程或显示更多代码。错误显示,文件正在使用中。是吗?可能是在GUI想要添加其他内容时复制了该文件。您好,是的,当windows服务试图将其复制到某个位置时,GUI将其附加到该文件时发生了错误。我能以某种方式避免这个例外吗?比如在附加之前检测文件是否正在使用?另外,通过C#“using”语句,异常已经被处理了?这就是为什么我问服务何时开始复制的原因?有什么触发事件吗?另外,using语句会自动关闭并处理streamwriter,因此您不需要sw.Close();如果我没有弄错的话。@meansomerandoms:你是对的,因为流调用Close()与调用Dispose()是一样的,所以“使用”足以确保流实例被关闭(无论代码成功还是出现异常,这一点都同样好)。嗨,Peter,谢谢。您的意思是将下面的代码转换为try/catch块吗?使用(StreamWriter sw=new StreamWriter(logfile,true)){sw.WriteLine(tick++“KYEC”+Environment.MachineName++“+msg);sw.Close();}@Peter Duniho:我刚才正在阅读上面的链接。我一直认为“using”关键字等同于try/catch。我想我弄错了。using语句未捕获调用streamwriter构造函数时产生的异常。因此,我应该将其更改为以下内容:try{using(var myObject=new MyClass()){//something here…}}catch(Exception ex){//Handle Exception}我的意思是将整个代码块包装在try/catch中。总之,这样做对于任何I/O代码都是一个好主意。I/O几乎总是有可能抛出异常,因此值得花时间考虑如果发生这种情况,您希望您的程序做什么,而不仅仅是将其留给.NET。就引用的讨论而言,在本例中,您希望整个“using”块完全包含在try/catch块中,因为“new StreamWriter…”表达式可能会引发异常(事实上,这可能就是异常的地方)。谢谢,我今天学到了一些东西。我修改了问题陈述中的代码;还没有在线测试。让我知道它是否正确。@sqr:请看abto的回答。假设您确信服务完成任务所需的时间不会超过两秒钟,那么您最初的编辑应该可以正常工作。但是重试循环更可靠。互斥锁更可靠。:)请注意,在服务代码端,如果不是互斥,您仍然需要重试,并且它将
    try
    {
        using (StreamWriter sw = new StreamWriter(logfile, true))
        {
            sw.WriteLine(tick + " " + "KYEC" + Environment.MachineName + " " + msg);
        }
    }
    catch (IOException ex)
    {
        WriteErrorLog("IOException " + ex.Message);
        System.Threading.Thread.Sleep(2000); //2 secs                
        using (StreamWriter sw = new StreamWriter(logfile, true))
        {
            sw.WriteLine(tick + " " + "KYEC" + Environment.MachineName + " " + msg);
        }
    }
// try to write maximum of 3 times
var maxRetry = 3;
for (int retry = 0; retry < maxRetry; retry++)
{
    try
    {
        using (StreamWriter sw = new StreamWriter(logfile, true))
        {
            sw.WriteLine("{0} KYEC{1} {2}", tick, Environment.MachineName, msg);

            break; // you were successfull so leave the retry loop
        }
    }
    catch (IOException)
    {
        if(retry < maxRetry - 1)
        {
            System.Threading.Thread.Sleep(2000); // Wait some time before retry (2 secs)
        }
        else
        {
            // handle unsuccessfull write attempts or just ignore.
        }
    }
}
 //To write file use
    using (FileStream fs = new FileStream(fileToReadPath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) 
    {
        using (StreamWriter StreamWriter = new StreamWriter(fs)) 
        {
            StreamWriter.WriteLine(tick + " " + "KYEC" + Environment.MachineName + " " + msg);
            StreamWriter.Close();
        }
    }

//To copy file use
    using (FileStream inStream = new FileStream(fileToReadPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
    {
        using (FileStream outStream = File.Create(fileToWritePath)) 
        {
            while (inStream.Position < inStream.Length) 
            {
                outStream.WriteByte((byte)inStream.ReadByte());
            }
        }
    }