获取数据时 GUI 没有响应

发布于 2024-07-27 01:57:00 字数 1137 浏览 4 评论 0原文

我的应用程序经常使用 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 中的局部变量。

而且可能同时有很多查询,所以我不想冒险将其分配给全局变量。

My application often fetch data from a webpage using WebRequest, but it isn't possible to click buttons etc while it's fetching. I've understood that I have to use threads/a backgroundworker, but I can't get it to work properly; it doesn't make the GUI more respondable.

The code I want to apply some kind of threading on, so that it stops making my application unresponding:

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;
}

Edit: Thank you, lc, I had tried something pretty similar to that. But my problem with using the backgroundworker like that is; how do I get the queryResult back to the function which called (in my case SQLGet, and in your case) StartQuery?

In my example, the returned string is going to be used as a local variable in the void the string is called inside.

And there may be many queries at the same time, so I don't want to risk assigning it to a global variable.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

对岸观火 2024-08-03 01:57:00

以下是如何使用 BackgroundWorker< 的简单示例/code>,因为它适用于您的代码:

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;
}

您可能还希望允许取消、提供错误详细信息或在获取数据时提供可靠的反馈。 查看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
}

Here's a simple example of how to use the BackgroundWorker as it applies to your code:

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;
}

You may also wish to allow cancellation, provide error details, or provide robust feedback as it fetches data. Take a look at the example on the MSDN page for more details.

The result of your query will show up in the BackgroundWorker.RunWorkerCompleted event as e.Result (I've stored it as an instance variable in this case). If you're going to run many of these at the same time, you'll need a way to differentiate which query is which. So you should pass more than just a string to the method. Take this example:

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
}
吲‖鸣 2024-08-03 01:57:00

BackgroundWorker 是一个很好的解决方案,具有一些对取消和进度的内置支持。 您还可以仅使用 HttpWebRequest.BeginGetResponse 而不是 GetResponse 来启动异步 Web 请求操作。 这最终非常简单,您可以设置进度回调。

有关您尝试执行的操作的确切示例,请参阅:

使用 HttpWebRequest 进行异步下载

BackgroundWorker is a good solution, with some built-in support for cancellation and progress. You can also just use HttpWebRequest.BeginGetResponse, rather than GetResponse, to initiate an asynchronous web request operation. This ends up being quite simple and you can set up a progress callback.

For an exact example of what you're trying to do, see:

Using HttpWebRequest for Asynchronous Downloads

夏日浅笑〃 2024-08-03 01:57:00

这是一个快速解决方案,应该很容易从中获取您需要的内容。

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;
            }
        }
    }
}

Here is a quick solution, should be easy to take what you need from it.

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;
            }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文