简体   繁体   中英

Having trouble running a function run asynchronously or as background worker

I'm trying to create an application that launches the GUI then AFTER it's already shown I want it to run another function that uses WebClient() and once it does it's query it's supposed to output to a label on the page. I've tried using on shown and a few other events but all of them stop the GUI from loading before it's finished making the query.

I've tried using a thread and it wouldn't allow updating the label since it was on a different thread, I tried async but couldn't manage to get results for some reason and now i'm in the middle of trying a background worker and I'm not getting any errors but the labels aren't getting updated either.

right now I have something that looks like this

public project()
    {
        InitializeComponent();
        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += querysite;
    }

    private void querysite(object sender, DoWorkEventArgs e)
    {
        WebClient myWebClient = new WebClient();
        myWebClient.Headers.Add("user-agent", "libcurl-agent/1.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
        byte[] myDataBuffer = myWebClient.DownloadData("http://example.com/SystemStatus");
        string download = Encoding.ASCII.GetString(myDataBuffer);
        if (download.IndexOf("is online") !=-1)
        {
            systemStatusLabel.Text = "System is up";
        }
        else
        {
            systemStatusLabel.Text = "System is down!";
        }

        throw new NotImplementedException();
    }

Is there something i'm doing wrong? Is there a better way to accomplish this? I've been stuck on this for a couple of hours and can't find anything that does what I need it to do.

I have modified your code a bit, to work with a BackgroundWorker .
I have also allowed myself to do a bit of separation between the logic action of quering the site, and updating the GUI.
This should work for you:

    public project()
    {
        InitializeComponent();



        BackgroundWorker bw = new BackgroundWorker() { WorkerReportsProgress = true };
        bool isOnline = false;
        bw.DoWork += (sender, e) =>
        {

            //what happens here must not touch the form
            //as it's in a different thread
            isOnline = querysite();


        };

        bw.ProgressChanged += (sender, e) =>
        {
            //update progress bars here

        };

        bw.RunWorkerCompleted += (sender, e) =>
        {
            //now you're back in the UI thread you can update the form

            if (isOnline)
            {
                systemStatusLabel.Text = "System is up";
            }
            else
            {
                systemStatusLabel.Text = "System is down!";
            }


        }; 

    }

    private bool querysite()
    {
        WebClient myWebClient = new WebClient();
        myWebClient.Headers.Add("user-agent", "libcurl-agent/1.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
        byte[] myDataBuffer = myWebClient.DownloadData("http://example.com/SystemStatus");
        string download = Encoding.ASCII.GetString(myDataBuffer);
        bool isOnline = download.IndexOf("is online") != -1;
        return isOnline;            

    }  

When you want the query to be done, you need to call bw.RunWorkerAsync(); .

You're trying to update something on the UI thread from a different thread, that won't work out. You can create a delegate to update the text though, this is a simple way to accomplish that.

this.Invoke((MethodInvoker) delegate { systemStatusLabel.Text = "System is up"; });

The asynchronous programming model with async and await provides and easy to understand and maintain way of coding.

There's no need for another asynchronous work manager (like the BackgroundWorker ) ohter than what's provided byt the language and conforming APIs.

Supposing some UI event is triggering the start of the work, all you have to do is:

private async void MyEvent(object sender, EventHandler e)
{
    systemStatusLabel.Text = await GetSystemStatusAsync();
}

private async Task<string> GetSystemStatusAsync()
{
    WebClient myWebClient = new WebClient();
    myWebClient.Headers.Add("user-agent", "libcurl-agent/1.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
    var myDataBuffer = await myWebClient.DownloadDataTaskAsync("http://example.com/SystemStatus");
    string download = Encoding.ASCII.GetString(myDataBuffer);
    if (download.IndexOf("is online") !=-1)
    {
        return "System is up";
    }
    else
    {
        return "System is down!";
    }
}

Altough the new TaskAsync suffixed methods of the WebClient conform to this new way of coding, I would recommend you to use the HttpClient which was developed with this new way of coding in mind.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM