串口通信中,受到,发送的数据都被写入到了每天的日志文件中。
但是偶尔也,会出现,如下的提示。
An unhandled exception of type “system.IO.IOException” occurred in mscorlib.dll.
Additional information: The process cannot access the file “c:\mydata\20080715-MSG.log” because it is used by another process.我搞不清楚日志文件,为何会被多个进程访问。日志写入的代码如下
public static void LogFile(string comment)
        {
            string filename = Application.StartupPath + "\\" + global.SystemInfo_LogName() + "-MSG.Log";
            StreamWriter sw = new StreamWriter(filename, true);
            sw.WriteLine(comment);
            sw.Close();
        }//通过串口发信的时候
public static void LogSendFile(string strSendAscii, DateTime dt)
        {
            //
            //DateTime dt = DateTime.Now;
            int i;
            string strTime = string.Format("{0:d2}:{1:d2}:{2:d2}", dt.Hour, dt.Minute, dt.Second);
            string strDateTime = string.Format("{0} {1} {2:d3}", dt.ToShortDateString(), strTime, dt.Millisecond);
            string strHex = "";
            for (i = 0; i < strSendAscii.Length; i++)
            {
                string t = strSendAscii.Substring(i, 1).ToString();
                short xxx = global.CSharpASC(t);
                string tt = "0" + xxx.ToString("X");
                strHex += "-" + tt.Substring(tt.Length - 2, 2);
            }            string strTemp = strDateTime + ",H->R:Recv" + strSendAscii + "\r\n";
            string strLogText = strDateTime + " " + strHex + " " + strSendAscii;
            LogFile(strLogText);
        }
        
        //通过串口受信的时候
        public static void LogRecvFile(string strReceiveAscii, DateTime dt)
        {
            //
            int i;
            string strTime = string.Format("{0:d2}:{1:d2}:{2:d2}", dt.Hour, dt.Minute, dt.Second);
            string strDateTime = string.Format("{0} {1} {2:d3}", dt.ToShortDateString(), strTime, dt.Millisecond);
            string strHex = "";
            for (i = 0; i < strReceiveAscii.Length; i++)
            {
                string t = strReceiveAscii.Substring(i, 1).ToString();
                short xxx = global.CSharpASC(t);
                string tt = "0" + xxx.ToString("X");
                strHex += "-" + tt.Substring(tt.Length - 2, 2);
            }            string strTemp = strDateTime + ",H->R:Recv" + strReceiveAscii + "\r\n";
            string strLogText = strDateTime + " " + strHex + " " + strReceiveAscii;
            LogFile(strLogText);
        }
主程序是通过收发串口的命令,来控制机器人动作的。
机器人的主要有,回到初始位置,取,放
Main()中有一个大的while()来处理机器人动作的循环。   //如果命令缓冲区中,有让机器人回到初始位置的命令
while (global.CmdSequenceCheck("ORIG") && !end_flg)
                {
                    Application.DoEvents();
                    //如果通过WaitPrimaryOrigMsg()得到了让机器人回到初始位置的命令
                    if (global.OrigStepState == 0 && global.WaitPrimaryOrigMsg())
                        global.OrigStepState = 1;  //那么机器人的状态切换                    if (global.OrigStepState == 1)
                    {   //那么机器人就回答说,我知道了,通过串口送回去
                        string strSend = global.EchoAutoAnswerOrig(true, "00", "00");
                        SendMsg(strSend);// 通过串口送回去
                        global.OrigStepState = 2; //然后机器人的状态切换
                    }
                    //rebot ORIG動作
                    //然后,机器人执行回到初始位置的动作
                    if (global.OrigStepState == 2)
                    {
                        timerGap.Interval = 15000;
                        timerGap.Start();
                        do
                        {
                            Application.DoEvents();
                            Thread.Sleep(1);
                        } while (timerGap.Enabled);
                        mapRobot.bOrigPoint = true;
                        global.OrigStepState = 3;//状態管理
                    }
                    if (global.OrigStepState == 3)
                    {//机器人回到原点后,告诉服务器,说,我已经回到原点了。
                        string strSendTemp = global.PrimaryEvt1Send(true,
                                        strSeq, global._ReceiveCommand._shaft,
                                        strLArmErrorCode, strMArmErrorCode, strHArmErrorCode,
                                        strHand1ST, strHand2nd);
                        SendMsg(strSendTemp);
                        global.OrigStepState = 4;//那么状态前进
                      }
                    //Waiting host answer...
      //之后,机器人等待服务器说----我已经知道你回到原点了
                    //机器人是通过WaitEchoEvt1OrigMsg()来得知服务器的回答消息的
                    if (global.OrigStepState == 4 && global.WaitEchoEvt1OrigMsg())
                    { //状態回復
                        global.OrigStepState = 0;
                        global.CmdSequenceAdminDelete("ORIG");
                        //之后,收信缓冲区之中的orig清除,
                        //以便于处理其他的命令
             }
             //那么可以看出,一共需要4步的交互动作。
             //需要不停的把串口的消息,写入到日志文件
        }// orig while end        While(){
            //Get 的命令处理,取物品
            //诸多的命令,都类似于上面,都是采用一问一答的方式,
            //而且是很多步的交互动作
            //get动作需要12步左右
}
        While(){
            //put 的命令处理,放物品
}
    }//处理整个动作命令的while循环,
    1.我自己想,不可能再有其他程序来访问日志文件,只有我自己的程序访问日志文件。
    2.这是不是由于程序中使用了大量的 Application.DoEvents();造成什么异步访问,我对此也不明白。
    3.对于我自己的程序中,多个进程同时访问日志,造成失败的原因,我不清楚。希望能得到大家的指点。
    4.如何控制,或者避免,多个进程同时访问一个文件呢?这些预防的方法,请大家告诉我好吗?
    我自己对于硬件的控制程序,经验不多。在调试时候发现,由于使用了DoEvent()后,程序就变得混乱不堪了。
    不是按照线性的方式执行,跳来跳去,代码也是并行的执行的。-----当然这是由于DoEvent()的特性造成的,这个我明白的。
    但是为什么,会造成多个进程来同时访问日志文件呢?是不是由于DoEvent()后,程序不是按照线性方式执行,而造成的呢?
    谢谢大家。敬礼!
    还有,上面的代码中 timerGap 定时器,采用的是System.Timers.Timer定时器,据说,可以处理多线程。
        public static System.Timers.Timer timerGap = new System.Timers.Timer();
   在此再次谢谢各位。

解决方案 »

  1.   

    你的程序需要运行多个实例吗?如果需要,可能会造成这种现象,如果不是,就比较奇怪了,加个Lock试一试public static void LogFile(string comment) 
            { 
                lock(类名)
    {
                string filename = Application.StartupPath + "\\" + global.SystemInfo_LogName() + "-MSG.Log"; 
                StreamWriter sw = new StreamWriter(filename, true); 
                sw.WriteLine(comment); 
                sw.Close(); 
    }
            } 
      

  2.   

    读文件时有冲突!!!
    加个锁lock试试!!!
      

  3.   

    应该是线程惹的,另外你要注意一下,LogFile有没有出错的时候,导致sw.Close(); 没有执行