2

伙计们,我有以下代码:

public static CookieContainer cookies;
public static HttpWebRequest GetNewRequest(string targetUrl, CookieContainer SessionCookieContainer)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(targetUrl);
        request.CookieContainer = SessionCookieContainer;
        request.AllowAutoRedirect = false;
        return request;
    }
    public async static Task<HttpWebResponse> MakeRequest(HttpWebRequest request, CookieContainer SessionCookieContainer, Dictionary<string, string> parameters = null)
    {
        HttpWebResponse response;
        request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.52 Safari/536.5Accept: */*";
        request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        request.CookieContainer = SessionCookieContainer;
        request.AllowAutoRedirect = false;
        if (parameters != null)
        {
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            string s = "";
            foreach (KeyValuePair<string, string> pair in parameters)
            {
                if (s.Length == 0)
                {
                    s = s + string.Format("{0}={1}", pair.Key, pair.Value);
                }
                else
                {
                    s = s + string.Format("&{0}={1}", pair.Key, pair.Value);
                }
            }
            byte[] bytes = Encoding.UTF8.GetBytes(s);
            using (Stream stream = await request.GetRequestStreamAsync())
            {
                stream.Write(bytes, 0, bytes.Length);
            }
        }
        request.Method = "GET";
        response = await request.GetResponseAsync() as HttpWebResponse;
        SessionCookieContainer.Add(response.Cookies);
        while (response.StatusCode == HttpStatusCode.Found)
        {
            response.Close();
            request = GetNewRequest(response.Headers["Location"], SessionCookieContainer);
            response = await request.GetResponseAsync() as HttpWebResponse;
            SessionCookieContainer.Add(response.Cookies);
        }
        return response;
    } 

我使用这个函数的一些方法(例如)

async Task<string> login(string url, string id, string pw)
    {
       ///code...
    }

我的问题是:如果我想得到结果buttonclick(object sender, EventArgs e)我该怎么办?

我已经尝试过了,但是没有用:

private void buttonclick(object sender, EventArgs e)
{
    string htmlPage=login(url, id, pw);
}

编辑

我已经解决了在和 voidasync之间添加和在之前添加的问题privateawaitlogin(bla bla)

4

2 回答 2

2

您的登录方法是异步的。简单来说,异步方法在调用时不会返回结果值,相反,异步方法会返回 TResult 的任务(登录方法的字符串任务)。Task 是一种特殊类型,它代表您计算结果值的承诺。为了获得结果,您应该:

  • 在 Tast 对象上调用 .Result 属性。这将阻塞调用者线程,直到计算出结果。(对 Windows 应用程序非常不利,因此它使应用程序无响应,甚至导致死锁(取决于同步方法的实现)
  • 使用 await 关键字异步等待,直到计算出结果值。这将使调用者(UI)线程在下载网页时可以自由执行其他操作。一旦任务完成(下载网页),UI 线程将在等待语句之后返回处理代码。这是 Windows 应用程序的首选,因为这允许应用程序保持响应。

尝试这个:

private async void buttonclick(object sender, EventArgs e)
{
    string htmlPage = await login(url, id, pw);
}
于 2013-11-07T22:43:59.267 回答
2

虽然以下是一个明显的解决方案,但它有隐藏的问题:

private async void buttonclick(object sender, EventArgs e)
{
    string htmlPage = await login(url, id, pw);
}
  • 如果login抛出异常怎么办?它不会被观察到,并且很可能会使应用程序崩溃。
  • 如果用户在之前的异步登录操作已经在进行的情况下单击了两次按钮怎么办?您当然不希望有两个挂起的登录。

这是一个稍微改进的版本:

Task<string> _pendingLogin = null;
private async void buttonclick(object sender, EventArgs e)
{
    if (_pendingLogin != null)
    {
        MessageBox.Show("Login pending...");
        return;
    }

    try
    {
        _pendingLogin = login(url, id, pw);
        string htmlPage = await _pendingLogin;
        MessageBox.Show("Logged in: " + htmlPage);
    }
    catch(Exception ex)
    {
        MessageBox.Show("Error in login: " + ex.Message);
    }

    _pendingLogin = null;
}
于 2013-11-07T23:05:08.483 回答