PostSubmitter的异步CTP

我正在尝试构建一个REST客户端使用Async CTP。 我是CTP的新手,因此,通过互联网上的一些例子,我得到了一个仅用于发布(GET或POST)的clas。 到目前为止这是class级:

using System; using System.Collections.Specialized; using System.IO; using System.Net; using System.Text; using System.Threading.Tasks; using System.Web; namespace RESTClient.Core { ///  /// Submits post data to a url. ///  public class PostSubmitter { #region Backing Store private string m_url = string.Empty; private NameValueCollection m_values = new NameValueCollection(); private PostTypeEnum m_type = PostTypeEnum.Get; #endregion #region Constructors ///  /// Default constructor. ///  public PostSubmitter() { } ///  /// Constructor that accepts a url as a parameter ///  /// The url where the post will be submitted to. public PostSubmitter(string url) : this() { m_url = url; } ///  /// Constructor allowing the setting of the url and items to post. ///  /// the url for the post. /// The values for the post. public PostSubmitter(string url, NameValueCollection values) : this(url) { m_values = values; } #endregion #region Properties ///  /// Gets or sets the url to submit the post to. ///  public string Url { get { return m_url; } set { m_url = value; } } ///  /// Gets or sets the name value collection of items to post. ///  public NameValueCollection PostItems { get { return m_values; } set { m_values = value; } } ///  /// Gets or sets the type of action to perform against the url. ///  public PostTypeEnum Type { get { return m_type; } set { m_type = value; } } #endregion ///  /// Posts the supplied data to specified url. ///  /// a string containing the result of the post. public async Task Post() { StringBuilder parameters = new StringBuilder(); for (int i = 0; i < m_values.Count; i++) { EncodeAndAddItem(ref parameters, m_values.GetKey(i), m_values[i]); } string result = await PostData(m_url, parameters.ToString()); return result; } ///  /// Posts the supplied data to specified url. ///  /// The url to post to. /// a string containing the result of the post. public async Task Post(string url) { m_url = url; return await this.Post(); } ///  /// Posts the supplied data to specified url. ///  /// The url to post to. /// The values to post. /// a string containing the result of the post. public async Task Post(string url, NameValueCollection values) { m_values = values; return await this.Post(url); } ///  /// Posts data to a specified url. Note that this assumes that you have already url encoded the post data. ///  /// The data to post. /// the url to post to. /// Returns the result of the post. private async Task PostData(string url, string postData) { HttpWebRequest request = null; if (m_type == PostTypeEnum.Post) { Uri uri = new Uri(url); request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = postData.Length; using (Stream writeStream = await request.GetRequestStreamAsync()) { UTF8Encoding encoding = new UTF8Encoding(); byte[] bytes = encoding.GetBytes(postData); writeStream.Write(bytes, 0, bytes.Length); } } else { Uri uri = new Uri(url + "?" + postData); request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "GET"; } string result = string.Empty; using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync()) { using (Stream responseStream = response.GetResponseStream()) { using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8)) { result = readStream.ReadToEnd(); } } } return result; } ///  /// Encodes an item and ads it to the string. ///  /// The previously encoded data. /// The data to encode. /// A string containing the old data and the previously encoded data. private void EncodeAndAddItem(ref StringBuilder baseRequest, string key, string dataItem) { if (baseRequest == null) { baseRequest = new StringBuilder(); } if (baseRequest.Length != 0) { baseRequest.Append("&"); } baseRequest.Append(key); baseRequest.Append("="); baseRequest.Append(HttpUtility.UrlEncode(dataItem)); } } } 

这就是我使用它的方式:

  private void ButtonSubmit_Click(object sender, EventArgs e) { ButtonReset.Enabled = false; TextResponse.Text = String.Empty; TextResponse.Text += "Begining..." + Environment.NewLine; try { TextResponse.Text += Task.Factory.StartNew(() => PostSomeData().Wait()); //TextResponse.Text += PostSomeData(); TextResponse.Text += Environment.NewLine; TextResponse.Text += "Function Done!" + Environment.NewLine; } catch (Exception ex) { TextResponse.Text += "Exception!" + Environment.NewLine + "Message: " + ex.Message + Environment.NewLine; } finally { ButtonReset.Enabled = true; TextResponse.Text += "Function Ended!"; } } private async Task PostSomeData() { PostSubmitter post = new PostSubmitter(); post.Url = TextURL.Text.Trim(); post.PostItems.Add(TextParam01.Text.Trim(), TextValue01.Text.Trim()); post.PostItems.Add(TextParam02.Text.Trim(), TextValue02.Text.Trim()); post.PostItems.Add(TextParam03.Text.Trim(), TextValue03.Text.Trim()); post.PostItems.Add(TextParam04.Text.Trim(), TextValue04.Text.Trim()); post.PostItems.Add(TextParam05.Text.Trim(), TextValue05.Text.Trim()); post.PostItems.Add(TextParam06.Text.Trim(), TextValue06.Text.Trim()); post.PostItems.Add(TextParam07.Text.Trim(), TextValue07.Text.Trim()); post.PostItems.Add(TextParam08.Text.Trim(), TextValue08.Text.Trim()); post.PostItems.Add(TextParam09.Text.Trim(), TextValue09.Text.Trim()); post.PostItems.Add(TextParam10.Text.Trim(), TextValue10.Text.Trim()); post.PostItems.Add(TextParam11.Text.Trim(), TextValue11.Text.Trim()); post.PostItems.Add(TextParam12.Text.Trim(), TextValue12.Text.Trim()); post.Type = PostTypeEnum.Post; return await post.Post(); } 

行为并不像预期的那样。 行TextResponse.Text += Task.Factory.StartNew(() => PostSomeData().Wait()); whiz-by和我没有例外,这里是结果字符串:

开始…… System.Threading.Tasks.Taskfunction完成! function结束!

现在,如果我正在使用POST,我会在上面之后得到一个例外。 挖掘exception会显示500内部服务器错误

但是,如果我使用GET,则没有任何反应。 没有例外,只有相同的最终结果。

我在PostSubmitter类中做错了吗?

以下是使用paramaeters拍摄的UI: UI Screen Shot http://img268.imageshack.us/img268/1010/restclient2.png

问候。

更新#1我也修改了UI上的click事件。 然而

  • 它仅在PostType为GET时有效 。 POST无效。
  • UI在操作持续时挂起

修改:

  private async void ButtonSubmit_Click(object sender, EventArgs e) { ButtonReset.Enabled = false; TextResponse.Text = String.Empty; TextResponse.Text += "Begining..." + Environment.NewLine; try { TextResponse.Text += await PostSomeData(); TextResponse.Text += Environment.NewLine; TextResponse.Text += "Function Done!" + Environment.NewLine; } catch (Exception ex) { TextResponse.Text += "Exception!" + Environment.NewLine + "Message: " + ex.Message + Environment.NewLine; } finally { ButtonReset.Enabled = true; TextResponse.Text += "Function Ended!"; } } 

您的代码只是部分异步; 好好看看PostData

特别是, ReadToEnd需要是异步的:

 private async Task PostData(string url, string postData) { HttpWebRequest request = null; if (m_type == PostTypeEnum.Post) { Uri uri = new Uri(url); request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = postData.Length; using (Stream writeStream = await request.GetRequestStreamAsync()) { UTF8Encoding encoding = new UTF8Encoding(); byte[] bytes = encoding.GetBytes(postData); await writeStream.WriteAsync(bytes, 0, bytes.Length); } } else { Uri uri = new Uri(url + "?" + postData); request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "GET"; } using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync()) using (Stream responseStream = response.GetResponseStream()) using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8)) { return await readStream.ReadToEndAsync(); } } 

除了让其他人提到的事件处理程序异步之外,这也是一个补充。

尝试以下方法:

 private async void ButtonSubmit_Click(object sender, EventArgs e) { ButtonReset.Enabled = false; TextResponse.Text = String.Empty; TextResponse.Text += "Begining..." + Environment.NewLine; TextResponse.Text += await PostSomeData(); TextResponse.Text += Environment.NewLine; TextResponse.Text += "Function Done!" + Environment.NewLine; } 

您需要在客户端中使用asyncawait关键字。 改变这两行你应该是好的:

 private void ButtonSubmit_Click(object sender, EventArgs e) { => private async void ButtonSubmit_Click(object sender, EventArgs e) { TextResponse.Text += Task.Factory.StartNew(() => PostSomeData().Wait()); => TextResponse.Text += await PostSomeData();