login about faq

We have a series of web service api endpoints that we use that will do some movements of files via FTP and other web requests. Since the underlying processes task advantage of many of the async Task processes when we call things like .Wait/Result we will end up blocking (which is by design). For the sleep state for our methods, we're using the Task.Delay (as shown in the sample below).

This is my first shot of using Chilkat in an async fashion, If there was a better way of doing this or if this is at least a sane approach?

Second part of the question, wrapping the Chilkat.Ftp2 in a using statement, I haven't seen samples that show this, but I would assume since it's implements IDisposible that using the using syntax would be the ideal approach. Any advantages/disadvantages of this in the scope of Chilkat?

public async Task DeleteRemoteFileAsync(string url, string path, string filename, string username, string password, CancellationToken ct)
{
  try
  {
    List<string> fileList = new List<string>();
    using (Chilkat.Ftp2 ftp = _GetFTPConnection(url, username, password))
    {
      if (!ftp.ChangeRemoteDir(path))
      {
        throw new Exception(ftp.LastErrorText);
      }
      Chilkat.Task task = ftp.DeleteRemoteFileAsync(filename);
      if (task == null)
      {
        throw new Exception(ftp.LastErrorText);
      }
      if (!task.Run())
      {
        throw new Exception(ftp.LastErrorText);
      }
      while (!task.Finished && !ct.IsCancellationRequested)
      {
        //Sleep 100 ms.
        await Task.Delay(100, ct);
      }
      ftp.Disconnect();
    }
  }
  catch (Exception ex)
  {
    throw ex;
  }
}

private Chilkat.Ftp2 _GetFTPConnection(string url, string username, string password)
{
  try
  {
    Chilkat.Ftp2 ftp = new Chilkat.Ftp2();
    if (!ftp.UnlockComponent(CHILKATFTPKEY))
    {
      throw new Exception(ftp.LastErrorText);
    }
    if (!ftp.IsUnlocked())
    {
      throw new Exception("Chilkat.Ftp2 is not unlocked");
    }

    ftp.Hostname = url;
    if (!ftp.ConnectOnly())
    {
      throw new Exception(ftp.LastErrorText);
    }
    ftp.Username = username;
    ftp.Password = password;
    if (!ftp.LoginAfterConnectOnly())
    {
      throw new Exception(ftp.LastErrorText);
    }
    return ftp;
  }
  catch (Exception ex)
  {
    ex.Data["Url"] = url;
    ex.Data["Username"] = username;
    throw ex;
  }
}

asked May 11 at 12:51

GarySmith's gravatar image

GarySmith
11


Hey Gary,

I wrote a wrapper around the Chilkat Ftp Class and provided Methods with Task Result. I did it something like this:

public Task<FtpDeleteFileInfo> DeleteFileAsync(string fileName) {
    ThrowIfDisposed();
    ThrowIfNotConnected();
    ThrowIfOperationIsAlreadyRunning();

    var ftpTask = mFtpClient.DeleteRemoteFileAsync(fileName);
    if (ftpTask == null) {
        return Task.FromResult(new FtpDeleteFileInfo(mFtpClient.LastErrorText));
    }
    if (!ftpTask.Run()) {
        return Task.FromResult(new FtpDeleteFileInfo(ftpTask.LastErrorText));
    }

    RefreshTaskCompletionSource();

    var task = Task.Run(async () => {
        var ckResult = await mTaskCompletionSource.Task;
        if (!ckResult.Finished) {
            return new FtpDeleteFileInfo(ckResult.LastErrorText);
        }
        if (!ckResult.IsCompleted()) {
            return new FtpDeleteFileInfo(ckResult.ErrorTextDependingOnState());
        }
        if (ckResult.GetResultBool()) {
            return new FtpDeleteFileInfo();
        }

        return new FtpDeleteFileInfo(ckResult.ResultErrorText);
    });
    task.ConfigureAwait(false);
    return task;

}

Edit: You need to add the following lines, too:

mFtpClient.OnTaskCompleted += FtpClientOnOnTaskCompleted; // Necessary to know when the task is finished
private void FtpClientOnOnTaskCompleted(object sender, Chilkat.TaskCompletedEventArgs args) {
    mTaskCompletionSource.SetResult(args.Task);
    mOperationRunning = false;
}

With this approach the caller can use the async/await features, while using the Chilkat Build-In Async functionality. To use it take a look at TaskCompletionSource<>. FtpDeleteFileInfo ect is a custom class of mine.

HTH Stefan

Ps: Maybe you can upvote this: http://www.chilkatforum.com/questions/9476/c-asyncawait-with-async-methods Would be great when Chilkat do that.

link

answered May 17 at 09:46

Stefan%20O's gravatar image

Stefan O
173

edited May 17 at 09:55

Thanks Stefan!

(May 17 at 09:50) chilkat ♦♦

See Asynchronous Programming with async and await (C#) for information about programming with async/await in C#.

In a nutshell, the C# async/await construct should be used with Chilkat's WinRT assembly which provides methods that return an IAsyncOperation, which corresponds to Task<tresult>. (This is C#'s Task class, not Chilkat's Task class.) You would do this if writing a WinRT (Windows Store) application. For example: http://www.example-code.com/csharp_winrt/ftp_download.asp

The asynchronous functionality of Chilkat for all other programming languages / environments is to return a Chilkat.Task object. An application can then start the task, go and do something else, check to see if it's finished, potentially get a TaskCompleted callback (depending on the programming language), etc. This has no relation to the async/await pattern in WinRT.

The Chilkat.Task asynchronous functionality is cross-language/cross-platform, and isn't quite the same as the async/await pattern in C#. The async/await pattern is really syntactic sugar -- the compiler generates code to do this: alt text

The non-WinRT Chilkat Async methods return a Chilkat.Task, which is the method call and arguments packaged up in a Chilkat.Task object that can be run at a later time. When you call Task.Run, the task is scheduled to run on a thread in Chilkat's background thread pool.

link

answered May 11 at 17:58

chilkat's gravatar image

chilkat ♦♦
11.8k316358420

edited May 11 at 17:58

Yep, that makes sense, generally how I use async. In the code above I'm using the native Chilkat.Task to do the task processing but calling the Task.Delay() inside the loop. My general thought is that this is more conductive way to release to the main thread for a web based app, whereas in the past I have seen Thread.Sleep() block the main thread, which for a web API service blocks the await thread in total (which case easily be seen calling any task with .Wait() or .Result). So a follow up, does this code above pose any danger?

(May 11 at 18:08) GarySmith
Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or __italic__
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×33
×21
×9

Asked: May 11 at 12:51

Seen: 855 times

Last updated: May 17 at 09:55

powered by OSQA