无法运行函数异步运行或作为后台工作程序运行

时间:2014-02-23 05:17:47

标签: c# multithreading backgroundworker async-await

我正在尝试创建一个启动GUI的应用程序,然后它已经显示我希望它运行另一个使用WebClient()的函数,一旦它执行它的查询,它应该输出到页面上的标签。我已尝试使用show和其他一些事件,但所有这些事件都会在完成查询之前停止加载GUI。

我尝试过使用一个线程并且它不允许更新标签,因为它在不同的线程上,我尝试了异步,但由于某种原因无法获得结果,现在我正处于中间位置尝试后台工作者,我没有收到任何错误,但标签也没有得到更新。

现在我有一些看起来像这样的东西

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

我有什么问题吗?有没有更好的方法来实现这一目标?我已经被困在这几个小时了,找不到任何可以做我需要做的事情。

3 个答案:

答案 0 :(得分:2)

我稍微修改了您的代码,使用BackgroundWorker 我还允许自己在查询站点的逻辑操作和更新GUI之间做一些分离 这应该适合你:

    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;            

    }  

如果要完成查询,则需要调用bw.RunWorkerAsync();

答案 1 :(得分:1)

您正在尝试从其他线程更新UI线程上的某些内容,这将无法解决。您可以创建一个委托来更新文本,这是一种简单的方法来实现它。

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

答案 2 :(得分:0)

The asynchronous programming model with async and await提供且易于理解和维护的编码方式。

不需要另外的异步工作管理器(比如BackgroundWorker),而不需要语言和符合API提供的工作管理器。

假设某些UI事件触发了工作的开始,您所要做的就是:

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

尽管WebClient的新 TaskAsync 后缀方法符合这种新的编码方式,但我建议您使用以这种新方式开发的HttpClient记住编码。