GUI在获取数据时没有响应

Pho*_*exo 1 c# multithreading webrequest backgroundworker winforms

我的应用程序通常使用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;
}
Run Code Online (Sandbox Code Playgroud)

编辑:谢谢,lc,我曾尝试过类似的东西.但是我使用这样的背景工作者的问题是; 如何将queryResult返回到调用的函数(在我的情况下是SQLGet,在你的情况下)是StartQuery?

在我的示例中,返回的字符串将用作内部调用字符串的void中的局部变量.

并且可能同时存在许多查询,因此我不希望冒险将其分配给全局变量.

lc.*_*lc. 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;
}
Run Code Online (Sandbox Code Playgroud)

您可能还希望在获取数据时允许取消,提供错误详细信息或提供强大的反馈.有关详细信息,请查看MSDN页面上的示例.

您的查询结果将在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
}
Run Code Online (Sandbox Code Playgroud)