【新手求教】关于C#循环无法跳出问题,代码片段如下

最近遇到了个问题,主要是在做一个异步通讯的时候会一直循环在某个代码段,始终无法跳出,还望各位大神给个建议

8个回答

会调试吗?在ide里面加断点调试下或者多加几个打印输出看下结果,确定问题在哪里


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;
using System.Net.Sockets;
using RetDLL;
using System.Collections; //在C#中使用ArrayList必须引用Collections类
using System.Diagnostics;

namespace PTVKey
{
class ThreadServer:Form1
{
private byte[] recvBuffer;//存放消息数据
private Socket socket;//为客户端建立的SOCKET连接
public Form1 form1;
private bool bStop;
private bool bResult;
public int indexStra;
public string getkeymsg;
private Thread thread;
public string cmd ="00#0";
private KeyInfo keyInfo;

    public ThreadServer()
    {

    }

    public ThreadServer(Socket s, Form1 frm)
    {
        this.form1 = frm;
        this.socket = s;
        recvBuffer = new byte[65535];
        bStop = false;
        bResult = false;
    }

     public void End()
    {
        bStop = true;
    }

    public void Start()
    {
        socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, 0, new AsyncCallback(RecieveCallBack), socket);
        Thread.Sleep(50);

        SendKey();
        //开始心跳线程
        thread = new Thread(Run);
        thread.Start();   
    }

    private Ret SendKey()
    {
        Ret ret = new Ret(true);

        keyInfo = new KeyInfo();
        ret = GetKeyFromDB(ref keyInfo);
        if (!ret.b)
        {
            return ret;
        }
        //SET#KEY#160#字符串
        string key = keyInfo.mainKey.Trim() ;
        string msg = "SET#KEY#" + key.Length.ToString() + "#" + keyInfo.mainKey;
        ret = sendServerMsg(msg);

        return ret; 
    }


    #region 功能函数

    /// <summary>
    /// 从数据库中获取一条未使用的KEY
    /// </summary>
    /// <returns></returns>
    private Ret GetKeyFromDB(ref KeyInfo keyInfo)
    {
        Ret ret = new Ret(true);

        DBData dd = new DBData();
        string strSQL = string.Format("select top 1 * from key_info where batchId= {0} and status = 0 order by createTime asc" , Program.batchInfo.id);

        ArrayList list = new ArrayList();
        int cnt = dd.getKeInfo(strSQL, ref list);
        if (cnt <= 0)
        {
            ret.b = false;
            return ret;
        }
        keyInfo = (KeyInfo)list[0];

        return ret; 
    }

    /// <summary>
    /// 修改数据库中key使用状态
    /// </summary>
    /// <returns></returns>
    private Ret ModifyKeyStatus()
    {
        Ret ret = new Ret(true);

        string strSQL = string.Format("update  key_info set status = 1 where batchId= {0} and id = {1}", Program.batchInfo.id , keyInfo.id);
        DB db = new DB();
        int res = db.executeSQLNonQuery(strSQL);
        if (res <= 0)
        {
            ret.b = false;
        }
        return ret; 
    }
    #endregion 


    static bool IsSocketConnected(Socket s)
    {
        return !((s.Poll(1000, SelectMode.SelectRead) && (s.Available == 0)) || !s.Connected);
    }


    private  void Run()
    {
        string strip = socket.RemoteEndPoint.ToString();
        while (!bStop)
        {
            bool b = IsSocketConnected(socket);
            if (!b)
            {
                break;
            }
            Thread.Sleep(200);
        }

        for (int i = 0; i < 3; i++)
        {
            string output;
            RunCmd("arp -d", out output);
            Thread.Sleep(200);
        }
        try
        {
            Thread.Sleep(100);
            if (socket.Connected)
            {
                socket.Close();
            }
            form1.trace(strip + " 断开了服务器连接.");
        }
        catch
        {
            form1.trace(strip + " 断开了服务器连接.");
        }
        try
        {
            thread.Abort();
        }
        catch(Exception ex)
        {
            string str = ex.Message.ToString();
        }
    }


    private void RecieveCallBack(IAsyncResult AR)
    {
        try
        {
            Socket RSocket = (Socket)AR.AsyncState;
            int REnd = RSocket.EndReceive(AR);
            RSocket.BeginReceive(recvBuffer, 0, recvBuffer.Length, 0, new AsyncCallback(RecieveCallBack), RSocket);
            //转换  
            string recvMsg = Encoding.ASCII.GetString(recvBuffer, 0, REnd);
            // string recvMsg = Encoding.Unicode.GetString(recvBuffer, 0, REnd);
            HandleMsg(recvMsg);
        }
        catch
        {
            //解析处理结果
            bResult = false;
            bStop = true;
        }
    }


    private Ret HandleMsg(string msg)
    {
        Ret ret = new Ret(true);

        if (msg == "" || msg.Length <= 0)
        {
            ret.b = false;
            ret.str = "接收消息为空";
            //Process.GetCurrentProcess().Kill();
            form1.trace1(ret.str);
            return ret;


         }
        else
        {          

            form1.trace("服务器收到消息:" + msg);
            indexStra = msg.LastIndexOf("#") + 1;//获取最后一个#之后的字符串
            string a = msg.Substring(indexStra, msg.Length - indexStra);
            int b = a.LastIndexOf("\t") + 1;
            getkeymsg = a.Substring(b, a.Length - b);


            //SET#KEY#字符串长度#字符串
            if (msg.Contains("SET"))
            {
                if (msg.Contains("FAIL"))
                {
                    //设置失败:界面展示;发送停止指令
                    form1.trace("设置Key失败");
                    form1.resultDisp("NG", System.Drawing.Color.DarkRed);
                    form1.keyDisp(keyInfo.mainKey);


                    string cmd = "00#0";
                    sendServerMsg(cmd);
                }
                else
                {
                    //这里可以检测服务器传递过来的KEY是否正确
                    string strSQL = string.Format("select * from  key_info where  key3 = '" + getkeymsg + "' and status = 0 ");//判断数据库里面是是否有该key
                    Ret ret1 = new Ret(true);
                    DBData dd1 = new DBData();
                    ArrayList list1 = new ArrayList();
                    int cnt = dd1.getKeInfo(strSQL, ref list1);
                    if (cnt <= 0)
                    {
                        form1.trace("检查结束 传递服务器传递的KEY值不正确");
                        form1.resultDisp("NG", System.Drawing.Color.Red);
                        form1.keyDisp(keyInfo.mainKey);
                        string cmd = "00#0";
                        sendServerMsg(cmd);

                    }
                    //发送GET#KEY#CHECKOK
                    else
                    {
                        string cmd = "GET#KEY#CHECKOK";
                        sendServerMsg(cmd);
                        form1.trace("检查结束 KEY值正确");

                    }
                }
            }
            if (msg.Contains("GET"))
            {
                if (msg.Contains("FAIL"))
                {
                    //设置失败:界面展示;发送停止指令
                    form1.trace("设置Key失败");
                    form1.resultDisp("NG", System.Drawing.Color.Red);

                    ThreadServer ss = new ThreadServer();
                    ss.End();

                }
                else
                {
                    //更新数据库当前Key使用状态
                    ret = updateStatus();
                    if (!ret.b)
                    {
                        form1.trace1("设置Key失败");
                        form1.resultDisp("NG", System.Drawing.Color.Red);
                        ThreadServer ss = new ThreadServer();
                        ss.End();

                    }
                    else
                    {
                        form1.trace1("设置Key成功");
                        form1.resultDisp("PASS", System.Drawing.Color.DarkGreen);
                        ThreadServer ss = new ThreadServer();
                        ss.End();
                    }
                }
                form1.keyDisp(keyInfo.mainKey);
                string cmd = "00#0";
                sendServerMsg(cmd);
                //
            }

            return ret;
        }
    }


    /// <summary>
    /// 发送消息到客户端(板子)
    /// </summary>
    /// <param name="msg"></param>
    /// <returns></returns>
    private Ret sendServerMsg(string msg)
    {
        Ret ret = new Ret(true);
        try
        {
            byte[] s = Encoding.ASCII.GetBytes(msg);
           // byte[] s = Encoding.Unicode.GetBytes(msg);
            socket.Send(s, 0, s.Length, 0);
            form1.trace("服务器发送消息:"+msg);
        }
        catch (Exception ey)
        {
            ret.b = false;
            ret.str = ey.Message.ToString();
            form1.trace("服务器发送异常:" + ret.str);
        }

        return ret;
    }

    #region 解析功能函数

    private static string CmdPath = @"C:\Windows\System32\cmd.exe";
    /// <summary>
    /// 执行cmd命令
    /// 多命令请使用批处理命令连接符:
    /// <![CDATA[
    /// &:同时执行两个命令
    /// |:将上一个命令的输出,作为下一个命令的输入
    /// &&:当&&前的命令成功时,才执行&&后的命令
    /// ||:当||前的命令失败时,才执行||后的命令]]>
    /// 其他请百度
    /// </summary>
    /// <param name="cmd"></param>
    /// <param name="output"></param>
    public  void RunCmd(string cmd, out string output)
    {
        cmd = cmd.Trim().TrimEnd('&') + "&exit";//说明:不管命令是否成功均执行exit命令,否则当调用ReadToEnd()方法时,会处于假死状态
        using (Process p = new Process())
        {
            p.StartInfo.FileName = CmdPath;
            p.StartInfo.UseShellExecute = false;        //是否使用操作系统shell启动
            p.StartInfo.RedirectStandardInput = true;   //接受来自调用程序的输入信息
            p.StartInfo.RedirectStandardOutput = true;  //由调用程序获取输出信息
            p.StartInfo.RedirectStandardError = true;   //重定向标准错误输出
            p.StartInfo.CreateNoWindow = true;          //不显示程序窗口
            p.Start();//启动程序

            //向cmd窗口写入命令
            p.StandardInput.WriteLine(cmd);
            p.StandardInput.AutoFlush = true;

            //获取cmd窗口的输出信息
            output = p.StandardOutput.ReadToEnd();
            p.WaitForExit();//等待程序执行完退出进程
            p.Close();
        }
    }

    private Ret updateStatus()
    {
        Ret ret = new Ret(true);

        try
        {
            string strSQL = string.Format("update key_info set status= 1 where batchId={0} and id={1}", Program.batchInfo.id, keyInfo.id);
            DB db = new DB();
            int cnt = db.executeSQLNonQuery(strSQL);
            if (cnt <= 0)
            {
                ret.b = false;
                ret.str = "更新数据库失败";
            }
        }
        catch(Exception ex)
        {
            ret.b = false;
            ret.str = ex.Message.ToString();
        }

        return ret; 
    }

    private string parseInfo(string info)
    {
        string str = "";
        int index = info.LastIndexOf("#");
        str = info.Substring(index+1);
        return str; 
    }
    /// <summary>
    /// 解析设备ID
    /// </summary>
    /// <param name="stbid"></param>
    /// <returns></returns>
    private string parseMacFromSTBID(string stbid)
    {
        string str = "";
        if (stbid.Length <= 12)
        {
            return str; 
        }
        return  stbid.Substring(stbid.Length-12);
    }

    /// <summary>
    /// 统计字符在字符串中出现的次数
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    private int StatisticsCount(string str)
    {
        string s = "#";
        int Star = 0;
        int Count = 0;

        while (Star != -1)
        {
            Star = str.IndexOf(s, Star);//获取字符的索引
            if (Star != -1)
            {
                Count++;
                Star++;
            }
        }
        return Count;
    }


    #endregion 

}

}

还希望大神给个代码,你就这样说,说到天上也没人能解决你的问题

New_child
安之老大爷 没有 代码我这写的差不多 可就是卡在循环了····讲道理应该跳出那一步的
2 年多之前 回复

private Ret HandleMsg(string msg)
{
Ret ret = new Ret(true);

    if (msg == "" || msg.Length <= 0)
    {
        ret.b = false;
        ret.str = "接收消息为空";
        //Process.GetCurrentProcess().Kill();
        form1.trace1(ret.str);
        return ret;


     }
            主要一直循环在这里 不知道为什么
Czhenya
Czhenya 说明这个if判断的条件存在问题啊 ,,,
2 年多之前 回复

看你的代码也不是自己写的,你可以再换一个代码,或者问写代码的人。如果都不行,就花点钱找个程序员吧。

建议你在这个地方逐步加断点调试或是加提示框

你加个断点调试下, 看看是不是你每次处理消息的地方 msg都是空的 所以跳不出去

很明显,这是一个通信线程,线程在不断地接收数据
public void Start()
{
socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, 0, new AsyncCallback(RecieveCallBack), socket);
Thread.Sleep(50);

    SendKey();
    //开始心跳线程
    thread = new Thread(Run);
    thread.Start();   
}

    这个函数里面有一个 socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, 0, new AsyncCallback(RecieveCallBack), socket);
    这是一个异步接收数据的方法,只要接收到数据,就会调用回调函数RecieveCallBack
    private void RecieveCallBack(IAsyncResult AR)
{
    try
    {
        Socket RSocket = (Socket)AR.AsyncState;
        int REnd = RSocket.EndReceive(AR);
        RSocket.BeginReceive(recvBuffer, 0, recvBuffer.Length, 0, new AsyncCallback(RecieveCallBack), RSocket);
        //转换  
        string recvMsg = Encoding.ASCII.GetString(recvBuffer, 0, REnd);
        // string recvMsg = Encoding.Unicode.GetString(recvBuffer, 0, REnd);
        HandleMsg(recvMsg);
    }
    catch
    {
        //解析处理结果
        bResult = false;
        bStop = true;
    }
}
    通过回调函数再去调用HandleMsg方法,所以你看到HandleMsg里面一直在循环,因为你一直在接收数据
    另外:Run()方法里面有一句       socket.Close();  跑了这个后,你的循环就会停掉.
    一般我们进行Socket通信时经常采用这种方法
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问