我的应用程序通常使用WebRequest从网页获取数据,但是在获取时无法单击按钮等。我明白我必须使用线程/背景工作者,但我不能让它正常工作;它不会使GUI更具响应性。
代码我想要应用某种线程,以便它不再使我的应用程序无响应:
public string SQLGet(string query)
{
string post = "q=" + query;
WebRequest request = WebRequest.Create("http://test.com");
request.Timeout = 20000;
request.Method = "POST";
byte[] bytes = Encoding.UTF8.GetBytes(post);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = bytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
WebResponse response = request.GetResponse();
requestStream = response.GetResponseStream();
StreamReader reader = new StreamReader(requestStream);
string ret = reader.ReadToEnd();
reader.Close();
requestStream.Close();
response.Close();
return ret;
}
编辑:谢谢,lc,我尝试过类似的东西。但是我使用这样的背景工作者的问题是;如何将queryResult返回到调用的函数(在我的情况下是SQLGet,以及在你的情况下)StartQuery?
在我的示例中,返回的字符串将用作内部调用字符串的void中的局部变量。
并且可能同时存在许多查询,因此我不想冒险将其分配给全局变量。
答案 0 :(得分:5)
以下是如何使用适用于您的代码的BackgroundWorker
的简单示例:
private void StartQuery(string query)
{
BackgroundWorker backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.RunWorkerAsync(query);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
e.Result = SQLGet((string)e.Argument);
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
queryResult = (string)e.Result;
}
您可能还希望在获取数据时允许取消,提供错误详细信息或提供强大的反馈。请查看示例on the MSDN page以获取更多详细信息。
您的查询结果将在BackgroundWorker.RunWorkerCompleted
事件中显示为e.Result
(在这种情况下,我将其存储为实例变量)。如果您要同时运行其中的许多内容,则需要一种方法来区分哪个查询。所以你应该传递的不仅仅是一个字符串。举个例子:
private int NextID = 0;
private struct QueryArguments
{
public QueryArguments()
{
}
public QueryArguments(int QueryID, string Query)
: this()
{
this.QueryID = QueryID;
this.Query = Query;
}
public int QueryID { get; set; }
public string Query { get; set; }
public string Result { get; set; }
}
private int StartQuery(string query)
{
QueryArguments args = new QueryArguments(NextID++, query);
BackgroundWorker backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.RunWorkerAsync(args);
return args.QueryID;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
QueryArguments args = (QueryArguments)e.Argument;
args.Result = SQLGet(args.Query);
e.Result = args;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
QueryArguments args = (QueryArguments)e.Result;
//args.Result contains the result
//do something
}
答案 1 :(得分:3)
BackgroundWorker是一个很好的解决方案,内置支持取消和进度。您也可以使用HttpWebRequest.BeginGetResponse而不是GetResponse来启动异步Web请求操作。这最终非常简单,您可以设置进度回调。
有关您尝试执行的操作的确切示例,请参阅:
答案 2 :(得分:2)
这是一个快速的解决方案,应该很容易从中获取所需的内容。
using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Text;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
BackgroundWorker b = new BackgroundWorker();
b.DoWork += new DoWorkEventHandler(b_DoWork);
b.RunWorkerCompleted += new RunWorkerCompletedEventHandler(b_RunWorkerCompleted);
b.RunWorkerAsync("My Query");
while(b.IsBusy)
{
}
Console.ReadLine();
}
static void b_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Result is string)
{
Console.WriteLine((string)e.Result);
}
}
static void b_DoWork(object sender, DoWorkEventArgs e)
{
if (e.Argument is string)
{
string post = "q=" + (string) e.Argument;
WebRequest request = WebRequest.Create("http://test.com");
request.Timeout = 20000;
request.Method = "POST";
byte[] bytes = Encoding.UTF8.GetBytes(post);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = bytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
WebResponse response = request.GetResponse();
requestStream = response.GetResponseStream();
StreamReader reader = new StreamReader(requestStream);
string ret = reader.ReadToEnd();
reader.Close();
requestStream.Close();
response.Close();
e.Result = ret;
}
}
}
}