如何防止应用程序冻结,同时检查大量 PDF 文件?
How to prevent the application from freezing, while checking a lot of PDF files?
我尝试创建一个检查大量 PDF 的程序。它可以从网络驱动器完成,只需几分钟。应用程序在此过程中全部冻结,我想避免这种情况。
我搜索了很多帖子和视频,但都没有在我的程序中实现它。我尝试了这段代码来理解它是如何工作的,但它也失败了...
async private void button1_Click(object sender, EventArgs e)
{
rtbx.AppendText($"Processing...\n");
// This webswite takes 1-2s to be loaded
await HeavyWork(@"https://aion.plaync.com/");
rtbx.AppendText($"End.\n");
}
public Task HeavyWork(string url)
{
List<string> lesinfos = new List<string>();
while (checkBox1.Checked == false)
{
using (WebClient web1 = new WebClient())
{
lesinfos.Add(web1.DownloadString(url));
}
rtbx.AppendText($"{lesinfos.Count}\n");
this.Refresh();
}
rtbx.AppendText($"Done !\n");
return Task.CompletedTask;
}
当我点击按钮时,我永远无法点击复选框,UI 也从不响应。
尝试将 DownloadStringTaskAsync(...)
与 `await 一起使用(参见下面的示例)。
public async Task HeavyWork(string url)
{
List<string> lesinfos = new List<string>();
while (checkBox1.Checked == false)
{
using (WebClient web1 = new WebClient())
{
var content = await web1.DownloadStringTaskAsync(url);
lesinfos.Add(content);
}
rtbx.AppendText($"{lesinfos.Count}\n");
this.Refresh();
}
rtbx.AppendText($"Done !\n");
}
注意:WebClient
被认为已过时,现在 recommended 使用 HttpClient
。
考虑到您被迫使用同步 API,您可以通过将阻塞调用卸载到 ThreadPool
线程来保持 UI 响应。用于此目的的工具是 Task.Run
method. This method is specifically designed for offloading work to the ThreadPool
。以下是如何使用它:
public async Task HeavyWork(string url)
{
List<string> lesinfos = new List<string>();
using (WebClient web1 = new WebClient())
{
while (checkBox1.Checked == false)
{
string result = await Task.Run(() => web1.DownloadString(url));
lesinfos.Add(result);
}
rtbx.AppendText($"{lesinfos.Count}\n");
this.Refresh();
}
rtbx.AppendText($"Done !\n");
}
注意 HeavyWork
方法签名中的 async
关键字。请注意 Task.Run
调用之前的 await
。请注意末尾缺少 return Task.CompletedTask
行。
如果您不熟悉 async/await 技术,这里有一个入门教程:Asynchronous programming with async and await。
我尝试创建一个检查大量 PDF 的程序。它可以从网络驱动器完成,只需几分钟。应用程序在此过程中全部冻结,我想避免这种情况。
我搜索了很多帖子和视频,但都没有在我的程序中实现它。我尝试了这段代码来理解它是如何工作的,但它也失败了...
async private void button1_Click(object sender, EventArgs e)
{
rtbx.AppendText($"Processing...\n");
// This webswite takes 1-2s to be loaded
await HeavyWork(@"https://aion.plaync.com/");
rtbx.AppendText($"End.\n");
}
public Task HeavyWork(string url)
{
List<string> lesinfos = new List<string>();
while (checkBox1.Checked == false)
{
using (WebClient web1 = new WebClient())
{
lesinfos.Add(web1.DownloadString(url));
}
rtbx.AppendText($"{lesinfos.Count}\n");
this.Refresh();
}
rtbx.AppendText($"Done !\n");
return Task.CompletedTask;
}
当我点击按钮时,我永远无法点击复选框,UI 也从不响应。
尝试将 DownloadStringTaskAsync(...)
与 `await 一起使用(参见下面的示例)。
public async Task HeavyWork(string url)
{
List<string> lesinfos = new List<string>();
while (checkBox1.Checked == false)
{
using (WebClient web1 = new WebClient())
{
var content = await web1.DownloadStringTaskAsync(url);
lesinfos.Add(content);
}
rtbx.AppendText($"{lesinfos.Count}\n");
this.Refresh();
}
rtbx.AppendText($"Done !\n");
}
注意:WebClient
被认为已过时,现在 recommended 使用 HttpClient
。
考虑到您被迫使用同步 API,您可以通过将阻塞调用卸载到 ThreadPool
线程来保持 UI 响应。用于此目的的工具是 Task.Run
method. This method is specifically designed for offloading work to the ThreadPool
。以下是如何使用它:
public async Task HeavyWork(string url)
{
List<string> lesinfos = new List<string>();
using (WebClient web1 = new WebClient())
{
while (checkBox1.Checked == false)
{
string result = await Task.Run(() => web1.DownloadString(url));
lesinfos.Add(result);
}
rtbx.AppendText($"{lesinfos.Count}\n");
this.Refresh();
}
rtbx.AppendText($"Done !\n");
}
注意 HeavyWork
方法签名中的 async
关键字。请注意 Task.Run
调用之前的 await
。请注意末尾缺少 return Task.CompletedTask
行。
如果您不熟悉 async/await 技术,这里有一个入门教程:Asynchronous programming with async and await。