我在下面的代码中报告方法process2()中的进度时遇到问题。我想在每一行被读取之后增加进度条,但是这样做会阻塞UI,使其失去响应。如果我注释掉progress.report()行,它将不再阻塞UI线程。有人知道为什么会发生这种情况吗?我该如何解决?
下面是可以粘贴到Starter WPF应用程序中的完全工作的代码。
单击“运行”按钮(在开始生成文件时可能会有一个小的停顿,等待生成文件完成后),然后尝试移动窗口,它将保持冻结状态。
警告:此代码将在bin\debug文件夹(或您的配置指向的任何内容)中生成一个文本文件。如果从网络路径运行此文件,它可能无法写入此文件,因此建议从本地磁盘运行。
主窗口.xaml.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Queue<string> queue = new Queue<string>();
List<string> stringsCollection = new List<string>() { "1_abc123_A_AA_zzz", "2_abc123_AAAA_zzz", "3_abc123_AAAAAA_zzz" };
int linesCount = 0;
int totalLines = 0;
string ASSEMBLY_PATH;
string file;
public MainWindow()
{
InitializeComponent();
ASSEMBLY_PATH = ReturnThisAssemblyPath();
file = ASSEMBLY_PATH + @"\test.txt";
generateFile();
}
private async void Button_Click2(object sender, RoutedEventArgs e)
{
linesCount = 0;
Progress<int> process2_progress;
this.progress.Value = 0;
this.status.Text = "";
process2_progress = new Progress<int>();
process2_progress.ProgressChanged += Process2_progress_ProgressChanged;
this.status.Text += "Searching..." + Environment.NewLine;
await Task.Run(() =>
{
totalLines = System.IO.File.ReadLines(file).Count();
foreach (string s in stringsCollection)
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
this.status.Text += "Searching " + s + Environment.NewLine;
}));
List<string> strCollection = Process2(s, process2_progress);
foreach (string str in strCollection)
queue.Enqueue(str);
}
});
this.status.Text += "DONE!!" + Environment.NewLine;
}
private void Process2_progress_ProgressChanged(object sender, int e)
{
linesCount += e;
this.progress.Value = linesCount * 100 / totalLines;
}
List<string> Process2(string inputString, IProgress<int> progress)
{
List<string> result = new List<string>();
foreach (string line in System.IO.File.ReadLines(file, new UTF8Encoding()))
{
progress.Report(1);
}
return result;
}
void generateFile()
{
this.status.Text += "Generating FIle..." + Environment.NewLine;
int count = 0;
using (StreamWriter sw = new StreamWriter(file, true))
{
do
{
sw.WriteLine(Guid.NewGuid().ToString());
count++;
} while (count < 51000);
}
this.status.Text += "Done Generating FIle!" + Environment.NewLine;
}
public string ReturnThisAssemblyPath()
{
string codeBase = Assembly.GetAssembly(typeof(MainWindow)).CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return System.IO.Path.GetDirectoryName(path);
}
}
}
主窗口.xaml
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox x:Name="status" Grid.Row="0"></TextBox>
<Button Grid.Row="2" Height="50" Click="Button_Click2">Run2</Button>
<ProgressBar x:Name="progress" Grid.Row="3" Height="20" ></ProgressBar>
</Grid>
</Window>