3

I'm using this FtpClient library to connect to mainframe from WinForms application. I'm using thread.Sleep for the thread to wait for the response before it starts reading, otherwise it freezes. Is there an alternative to do this?

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();
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
user558138
  • 167
  • 1
  • 3
  • 13

3 Answers3

4

Use async programming model:

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

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

    // do the stuff

    socket.EndConnect(result);
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
  • Its working for logging in, but while sending other commands(upload/download) i'm getting this error "Cannot block a call on this socket while an earlier asynchronous call is in progress.". – user558138 Jan 28 '11 at 09:21
  • @user558138: Sorry forgot to say that you need to call `EndConnect()` – abatishchev Jan 28 '11 at 09:51
  • I'm still getting the same error. clientSocket.Send(cmdBytes, cmdBytes.Length, 0); //on this line – user558138 Jan 28 '11 at 11:01
  • @user558138: Where do you put your `Send`?. Check out also [this example](http://msdn.microsoft.com/en-us/library/bew39x2a.aspx) – abatishchev Jan 28 '11 at 11:32
0

Yes , if you can work with .NET 4.0, you've the task API.

You may learn more by reading this article: http://www.codethinked.com/post/2010/01/25/NET-40-and-SystemThreadingTasks.aspx

It provides you a way of creating a flow in which a task waits until previous one has ended. Take a look!

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
0

Writing Thread.Sleep() is indeed a bad practice.

If you are actually doing a FTP client, use FtpWebRequest BeginGetResponse(asynccallback, object)

And pass the readResonse as a callback. It will be called exactly when the response is ready.

rds
  • 26,253
  • 19
  • 107
  • 134
  • Bad practice? I think not. But yes, there are other approaches that can work. – stefan Jan 27 '11 at 16:14
  • Ok, let's say it's a proof of bad design, then http://stackoverflow.com/questions/1457282/alternatives-to-thread-sleep-for-simulating-pauses – rds Jan 27 '11 at 19:23
  • i dont agree with that article. its speculative about why you use a thread.sleep(). sleeping a thread is in my book a good way of saying "i dont have anything to do, please do process something before i try again". Still. My idea of a decent sleep is on <100 milliseconds, not on seconds or minutes. – stefan Jan 27 '11 at 20:08
  • Looping when you actually need to wait for a result is a waste of CPU time. I think an asynchronous call is a better design. – rds Jan 28 '11 at 11:56