Exemplo n.º 1
0
        private Task SimplifiedTransferRequest(TransferMethod method, string fileName, string directory, string channelPassword, bool overwrite, bool resume, CancellationToken cancellationToken)
        {
            TaskCompletionSource <Error> taskCompletionSource = new TaskCompletionSource <Error>();

            // check if task is already canceled.
            if (cancellationToken.IsCancellationRequested)
            {
                // if yes, exit early.
                taskCompletionSource.SetCanceled();
                return(taskCompletionSource.Task);
            }

            // the return code can show up in FileTransferStatusReceived, and ServerError.
            // and both can signal the end of the operation.
            // that is why ServerError is mapped on to the handler for FileTransferStatusReceived
            // this way, the clean up code has to be written once.
            // CancellationToken does not directly signal the abort, but instead calls TryHaltTransfer.
            // which will result in a FileTransferStatusReceived.

            FileTransfer self = null;
            Task         startTask;
            string       returnCode = Connection.GetNextReturnCode(out startTask);
            // = null, to make the c# compiler happy.
            FileTransferStatusEventHandler eventHandler = null;

            eventHandler = (transfer, status) =>
            {
                if (transfer != self)
                {
                    return;
                }
                // any event for transfer signals the end of the operation
                Connection.FileTransferStatusReceived -= eventHandler;
                // translate the error code into task state
                switch (status)
                {
                case Error.FileTransferComplete: taskCompletionSource.SetResult(Error.Ok); break;

                case Error.FileTransferCanceled: taskCompletionSource.SetCanceled(); break;

                default: taskCompletionSource.SetException(Library.CreateException(status)); break;
                }
            };
            startTask.ContinueWith(antecendent =>
            {
                // failed to initiate a transfer
                Connection.FileTransferStatusReceived -= eventHandler;
                // pass exception to user
                taskCompletionSource.SetException(antecendent.Exception);
            }, cancellationToken, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Current);
            Connection.FileTransferStatusReceived += eventHandler;

            self = method(this, channelPassword, fileName, overwrite, resume, directory, returnCode);

            if (cancellationToken != CancellationToken.None)
            {
                // register cancellationToken
                cancellationToken.Register(() => Library.Api.TryHaltTransfer(self, true, null));
            }

            return(taskCompletionSource.Task);
        }