Thread.Sleep()的替代方法:在套接字读取之前

3

我正在使用这个FtpClient库从WinForms应用程序连接到主机。我使用thread.Sleep让线程在开始读取之前等待响应,否则它会冻结。有没有其他替代方法?

public void Login() 
{
    if (this.loggedin) this.Close();

    Debug.WriteLine("Opening connection to " + this.server, "FtpClient");

    IPAddress addr = null;
    IPEndPoint ep = null;

    try
    {
        this.clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        addr = Dns.Resolve(this.server).AddressList[0];
        ep = new IPEndPoint(addr, this.port);
        this.clientSocket.Connect(ep);
    }
    catch (Exception ex)
    {
        // doubtfull
        if (this.clientSocket != null && this.clientSocket.Connected) this.clientSocket.Close();

        throw new FtpException("Couldn't connect to remote server", ex);
    }

    **Thread.Sleep(4000);**
    this.readResponse();
    ...
}

private void readResponse()
{
    this.message = "";
    this.result = this.readLine();

    if (this.result.Length > 3)
        this.resultCode = int.Parse(this.result.Substring(0, 3));
    else
        this.result = null;
}

private string readLine()
{
    while (true)
    {
        this.bytes = clientSocket.Receive(this.buffer, this.buffer.Length, 0);
        this.message += ASCII.GetString(this.buffer, 0, this.bytes);

        if (this.bytes < this.buffer.Length) break;
    }

    string[] msg = this.message.Split('\n');
    if (this.message.Length > 2)
    {
        this.message = msg[msg.Length - 2];
        try { response = msg[msg.Length - 3]; }
        catch { }
    }
    else
    {
        this.message = msg[0];
    }

    if (this.message.Length > 4 && !this.message.Substring(3, 1).Equals(" ")) return this.readLine();

    if (this.verboseDebugging)
    {
        for (int i = 0; i < msg.Length - 1; i++)
        {
            Debug.Write(msg[i], "FtpClient");
        }
    }
    return message;
}

public void sendCommand(String command)
{
    if (this.verboseDebugging) Debug.WriteLine(command, "FtpClient");

    Byte[] cmdBytes = Encoding.ASCII.GetBytes((command + "\r\n").ToCharArray());
    clientSocket.Send(cmdBytes, cmdBytes.Length, 0);
    this.readResponse();
}
3个回答

4

使用异步编程模型:

socket.BeginConnect(ep, new AsyncCallback(Connected), socket);

void Connected (IAsyncResult result)
{
    var socket = (Socket)result.AsyncState;

    // do the stuff

    socket.EndConnect(result);
}

它可以用于登录,但在发送其他命令(上传/下载)时,我收到了这个错误消息:“Cannot block a call on this socket while an earlier asynchronous call is in progress.”。 - user558138
@user558138:抱歉,我忘了说你需要调用 EndConnect() - abatishchev
我仍然收到相同的错误。 clientSocket.Send(cmdBytes, cmdBytes.Length, 0); //在这一行 - user558138
@user558138:你把Send放在哪里?也可以查看这个例子 - abatishchev

0

0

不良实践?我认为不是。但是,确实有其他方法可以奏效。 - stefan
好的,假设这是一个糟糕设计的证明,那么可以参考以下链接:https://dev59.com/PnM_5IYBdhLWcg3wQQtd - rds
我不同意那篇文章。它对为什么使用thread.sleep()进行了推测。让线程休眠在我看来是一种很好的方式,表示“我没有事情可做,请在我再次尝试之前处理一些东西”。但是,我认为适当的休眠时间应该在100毫秒以下,而不是几秒钟或几分钟。 - stefan
循环等待结果是浪费 CPU 时间,我认为异步调用是更好的设计。 - rds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接