Fix Expect method

Improve BeginExpect to be implemented similar to other asynch methods
This commit is contained in:
olegkap_cp
2013-01-21 12:56:54 +00:00
parent db38a04f8a
commit 95abd4557b
2 changed files with 68 additions and 107 deletions
@@ -1,4 +1,5 @@
using System;
using Renci.SshNet.Common;
using System;
using System.Threading;
namespace Renci.SshNet
@@ -6,61 +7,17 @@ namespace Renci.SshNet
/// <summary>
/// Provides additional information for asynchronous command execution
/// </summary>
public class ExpectAsyncResult : IAsyncResult
public class ExpectAsyncResult : AsyncResult<string>
{
/// <summary>
/// Gets or sets the ShellStream that async result was created for.
/// </summary>
/// <value>The ShellStream.</value>
internal ShellStream ShellStream { get; private set; }
///// <summary>
///// Gets or sets the bytes received. If SFTP only file bytes are counted.
///// </summary>
///// <value>Total bytes received.</value>
//public int BytesReceived { get; set; }
///// <summary>
///// Gets or sets the bytes sent by SFTP.
///// </summary>
///// <value>Total bytes sent.</value>
//public int BytesSent { get; set; }
#region IAsyncResult Members
/// <summary>
/// Gets a user-defined object that qualifies or contains information about an asynchronous operation.
/// </summary>
/// <returns>A user-defined object that qualifies or contains information about an asynchronous operation.</returns>
public object AsyncState { get; internal set; }
/// <summary>
/// Gets a <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.
/// </summary>
/// <returns>A <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.</returns>
public WaitHandle AsyncWaitHandle { get; internal set; }
/// <summary>
/// Gets a value that indicates whether the asynchronous operation completed synchronously.
/// </summary>
/// <returns>true if the asynchronous operation completed synchronously; otherwise, false.</returns>
public bool CompletedSynchronously { get; internal set; }
/// <summary>
/// Gets a value that indicates whether the asynchronous operation has completed.
/// </summary>
/// <returns>true if the operation is complete; otherwise, false.</returns>
public bool IsCompleted { get; internal set; }
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="CommandAsyncResult" /> class.
/// Initializes a new instance of the <see cref="ExpectAsyncResult" /> class.
/// </summary>
/// <param name="shellStream">The shell stream.</param>
internal ExpectAsyncResult(ShellStream shellStream)
/// <param name="asyncCallback">The async callback.</param>
/// <param name="state">The state.</param>
internal ExpectAsyncResult(AsyncCallback asyncCallback, Object state)
: base(asyncCallback, state)
{
this.ShellStream = shellStream;
}
}
}
+60 -56
View File
@@ -55,7 +55,7 @@ namespace Renci.SshNet
internal ShellStream(Session session, string terminalName, uint columns, uint rows, uint width, uint height, int maxLines, IDictionary<TerminalModes, uint> terminalModeValues)
{
this._encoding = new Renci.SshNet.Common.ASCIIEncoding();
this._encoding = session.ConnectionInfo.Encoding;
this._session = session;
this._incoming = new Queue<byte>();
this._outgoing = new Queue<byte>();
@@ -368,70 +368,77 @@ namespace Renci.SshNet
var text = string.Empty;
// Create new AsyncResult object
var asyncResult = new ExpectAsyncResult(this)
{
AsyncWaitHandle = new ManualResetEvent(false),
IsCompleted = false,
AsyncState = state,
};
var asyncResult = new ExpectAsyncResult(callback, state);
// Execute callback on different thread
this.ExecuteThread(() =>
{
do
string expectActionResult = null;
try
{
lock (this._incoming)
do
{
if (this._incoming.Count > 0)
text = this._encoding.GetString(this._incoming.ToArray(), 0, this._incoming.Count);
if (text.Length > 0)
lock (this._incoming)
{
foreach (var expectAction in expectActions)
if (this._incoming.Count > 0)
text = this._encoding.GetString(this._incoming.ToArray(), 0, this._incoming.Count);
if (text.Length > 0)
{
var match = expectAction.Expect.Match(text);
if (match.Success)
foreach (var expectAction in expectActions)
{
var result = text.Substring(0, match.Index + match.Length);
var match = expectAction.Expect.Match(text);
for (int i = 0; i < match.Index + match.Length && this._incoming.Count > 0; i++)
if (match.Success)
{
// Remove processed items from the queue
this._incoming.Dequeue();
}
var result = text.Substring(0, match.Index + match.Length);
expectAction.Action(result);
for (int i = 0; i < match.Index + match.Length && this._incoming.Count > 0; i++)
{
// Remove processed items from the queue
this._incoming.Dequeue();
}
if (callback != null)
{
callback(asyncResult);
expectAction.Action(result);
if (callback != null)
{
callback(asyncResult);
}
expectActionResult = result;
}
((EventWaitHandle)asyncResult.AsyncWaitHandle).Set();
break;
}
}
}
}
if (timeout != null)
{
if (!this._dataReceived.WaitOne(timeout))
{
if (callback != null)
{
callback(asyncResult);
}
((EventWaitHandle)asyncResult.AsyncWaitHandle).Set();
if (expectActionResult != null)
break;
if (timeout != null)
{
if (!this._dataReceived.WaitOne(timeout))
{
if (callback != null)
{
callback(asyncResult);
}
break;
}
}
}
else
{
this._dataReceived.WaitOne();
}
} while (true);
else
{
this._dataReceived.WaitOne();
}
} while (true);
asyncResult.SetAsCompleted(expectActionResult, true);
}
catch (Exception exp)
{
asyncResult.SetAsCompleted(exp, true);
}
});
return asyncResult;
@@ -442,18 +449,15 @@ namespace Renci.SshNet
/// </summary>
/// <param name="asyncResult">The async result.</param>
/// <exception cref="System.ArgumentException">Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult.</exception>
public void EndExpect(IAsyncResult asyncResult)
public string EndExpect(IAsyncResult asyncResult)
{
var expectAsyncResult = asyncResult as ExpectAsyncResult;
if (expectAsyncResult != null && expectAsyncResult.ShellStream == this)
{
// Make sure that operation completed if not wait for it to finish
this.WaitHandle(asyncResult.AsyncWaitHandle);
var ar = asyncResult as ExpectAsyncResult;
return;
}
if (ar == null || ar.EndInvokeCalled)
throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult.");
throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult.");
// Wait for operation to complete, then return result or throw exception
return ar.EndInvoke();
}
/// <summary>
@@ -465,7 +469,7 @@ namespace Renci.SshNet
/// </returns>
public string Expect(string text)
{
return this.Expect(new Regex(Regex.Escape(text)), TimeSpan.Zero);
return this.Expect(new Regex(Regex.Escape(text)), TimeSpan.FromMilliseconds(-1));
}
/// <summary>
@@ -511,7 +515,7 @@ namespace Renci.SshNet
if (this._incoming.Count > 0)
text = this._encoding.GetString(this._incoming.ToArray(), 0, this._incoming.Count);
var match = regex.Match(text.ToString());
var match = regex.Match(text);
if (match.Success)
{