我在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()
暂时阻止主线程。为什么会发生这种情况,我该如何避免呢?
答案 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结束。