BeginInvoke阻止了WinForms应用程序

时间:2018-03-18 15:13:58

标签: c# winforms begininvoke

我在Visual Studio 2017中创建了一个新的WinForms项目。 然后我向Form1(screenshot)添加了一个按钮和文本框。

代码:

using System;
using System.Net;
using System.Windows.Forms;

namespace TestWinForms
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private delegate void FormDelegate();
        private void button1_Click(object sender, EventArgs e)
        {
            UseWaitCursor = true;
            button1.Enabled = false;

            BeginInvoke(new FormDelegate(delegate
            {
                using (WebClient web = new WebClient())
                {
                    web.Encoding = System.Text.Encoding.UTF8;
                    textBox1.Text = web.DownloadString("https://stackoverflow.com/");
                }

                UseWaitCursor = false;
                button1.Enabled = true;
            }));
        }
    }
}

当我点击button1时,窗口光标没有变为WaitCursor,当我将光标悬停在ControlBox按钮上时,它们不会发光"#34;。简而言之,BeginInvoke()暂时阻止主线程。为什么会发生这种情况,我该如何避免呢?

2 个答案:

答案 0 :(得分:3)

正如其他用户在评论中所说,DownloadString阻止了您的用户界面,而不是BeginInvoke,因为它等待下载完成。

您应该使用DownloadStringAsync

以另一种方式解决这个问题
private WebClient _web;

private void button1_Click(object sender, EventArgs e)
{
    UseWaitCursor = true;
    button1.Enabled = false;

    _web = new WebClient();
    _web.Encoding = System.Text.Encoding.UTF8;
    _web.DownloadStringCompleted += DownloadCompleted;
    _web.DownloadStringAsync("https://stackoverflow.com/");
}

private void DownloadCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    textBox1.Text = e.Result;
    UseWaitCursor = false;
    button1.Enabled = true;
    _web.Dispose();
}

答案 1 :(得分:1)

我的第二个Hans评论:BeginInvoke仅推迟执行。

您需要的是BackgroundWorker或(更好)使用async/await pattern

  data={
    "MyProject": {
        "_attributes": {
            "class": "ABC",
            "projectclass": "MyProject",
            "prjname": "PrjName",
            "enabled": "true"
        },
        "PrjProp": {
            "_attributes": {
                "name": "MyProject.save"
            },
            "_text": true
        }
    }
}
console.log(data.MyProject._attributes.projectclass);

}

DownloadStringTaskAsync将在工作进程上运行,因为它是等待的。当它运行时,UI线程将继续处理其他事件,然后在await语句之后继续执行,因为DownloadStringTaskAsync结束。