Re: Threading for FTP in C#

Tech-Archive recommends: Fix windows errors by optimizing your registry



I had fun writing this. It should keep you busy for a while.
FYI, I didn't try to build it, so check for type-o's.

Minimum "using" statments required:

using System;
using System.Windows.Forms;

Implementation (without class declaration):

private delegate void ShowStatusInvoker(string Text);
private delegate void FtpUploadInvoker(object client, object logs, TextBox txtSummary);
private FtpUploadInvoker ftpUploadInvoker; // Instance variable of delegate

public void DoUpload()
{
try
{
// Create a pointer to the doFTPUpload method
ftpUploadInvoker = new FtpUploadInvoker(t.doFTPUpload);

// Invoke the pointer asyncronously on a thread-pool thread.
// If the FTP class documentation states that the doFTPUpload method
// uses thread-pooling, then I recommend spawning a custom thread (not pooled)
// instead of using this implementation to prevent deadlocks.
// See System.Thread.Thread class.
IAsyncResult result = ftpUploadInvoker.BeginInvoke(client, logs, txtSummary,
new AsyncCallback(UploadComplete), null);

// Wait a maximum of 60 seconds for the invocation to complete
if (!result.IsCompleted && !result.AsyncWaitHandle.WaitOne(60000, false))
// Operation has not completed within the maximum time alotted
{
logs.addToLog("Upload Failed!");
logs.addToLog("Operation has not completed within the maximum time alotted");
}
}
catch (FtpUploadException eUpload)
{
logs.addToLog("Upload Failed!");
logs.addToLog(eUpload.ToString());
}
}

/// <summary>
/// Callback for doFTPUpload on a thread-pool thread. Do not call any
/// Begin* methods from within the context of this method to avoid thread-pool deadlocks.
/// </summary>
public void UploadComplete(IAsyncResult result)
{
if (ftpUploadInvoker != null)
// This method can be used to obtain the return value
// but it's not necessary since FtpUploadInvoker returns void
ftpUploadInvoker.EndInvoke(result);

// It is important to note that GUI calls must occur on the main window thread
// which is the thread that the message loop is executing on.
// Check Form.InvokeRequired and use the Invoke method to properly make GUI calls
// from this thread.
ShowStatus("Upload Complete");
}

/// <summary>
/// Displays the specified <paramref name="Text" /> using a thread-safe invocation.
/// </summary>
public void ShowStatus(string Text)
{
lock (this)
{
if (this.InvokeRequired) // Form.InvokeRequired
// It is assumed that this method will be defined within a derived Form class
this.Invoke(new ShowStatusInvoker(ShowStatusCore), new object[] { Text });
else
ShowStatusCore(Text);
}
}

/// <summary>
/// Displays the specified <paramref name="Text" />. This method is not thread-safe.
/// </summary>
private void ShowStatusCore(string Text)
{
txtStatus.Text = Text;
}

--
Dave Sexton
dave@xxxxxxxxxxxxxxxxxxx
-----------------------------------------------------------------------
"Asad" <asadikhan@xxxxxxxxx> wrote in message news:ae270bef.0504260858.6dfed7e7@xxxxxxxxxxxxxxxxxxxxx
> Hi,
>
> I am trying to write some threading code to my application. The reason
> I've been tempted to do this is because, I am doing some FTP uploads,
> and sometimes during the put method, the application just hangs ("Not
> Responding") instead of the regular timeout and return. I am using a
> library to perform FTP stuff and so there may be a bug in there. In
> any case, what I am concerned with is my application executing with
> graceful execution and termination. I have plenty of try and catch
> clauses inside the methods, and I even know which line is causing the
> problem (the put line), I even tried debugging it line by line, but
> sometimes it just hangs up. This is happening with only this one
> particular FTP server being run by a client.
>
> So, I am thinking if I should create a thread that calls the
> doFTPUpload method. If the method doesn't return within, say, 60
> seconds, I forcefully terminate the call and show an error to the user
> via GUI. The main idea is to keep the application from going into "Not
> Responding" state by running the error prone code in a different
> thread.
>
> Now I have never done threading before but have read about it. So I am
> hoping someone can push me in the right direction.
>
> I have a class called Transmission that has doFTPUpload method. It
> takes in three arguments, a client object (that contains information
> about the FTP such as server name, user id, password, etc.),a logs
> object which is used to enter information into log files, and a
> textbox txtSummary which shows information to user as upload
> progresses.
>
> I make a call from my main method as follows:
>
> try
> {
> t.doFTPUpload(client,logs,txtSummary);
> }
> catch (Exception eUpload)
> {
> logs.addToLog("Upload Failed!");
> logs.addToLog(eUpload.ToString());
> }
>
> Now how can I modify this code to start a new worker thread and make
> the call to doFTPUpload inside this thread. Also how can I put a
> timeout on it so that if the thread doesn't finish up in say 60
> seconds, I manually kill the thread and go on with my execution inside
> the main method?
>
> Thanks.
>
> Asad


.


Quantcast